EDITED! WORKING CODE
I have the following class:
class Medic
{
private readonly int codM;
private string numeM;
private string specialitate;
//i have a constructor and properties with get and set, correctly written
}
I added 3 textBoxes to the form to be filled, each one related to one of the class attributes.
After this i have a button, and if all 3 textbox fields are correctly completed, a new class object is created.
This object will be added to a List. And this list of objects I want to be displayed in a listBox, and be updated as I add new objects.
Also, I want to have 2 objects already in the List and displayed in the listBox as I run the program, created in the code I mean, not using the textBoxes, and the new entered objects to come after these. I barely know where to write the code to create these 2 objects, same as where is ok to create and populate the List of objects or to write the code to bind this list into the ListBox;
public partial class Form1 : Form
{
List<Medic> listaMedici = new List<Medic>();
Medic m1 = new Medic(0, "ion", "endocrinologie");
public Form1()
{
InitializeComponent();
listaMedici.Add(m1);
}
private void button1_AddObject_Click(object sender, EventArgs e)
{
if (textBox1_cod.Text == "")
errorProvider1.SetError(textBox1_cod, "Introduceti codul medicului!");
else if (textBox2_nume.Text == "")
errorProvider1.SetError(textBox2_nume, "Introduceti numele medicului");
else if (Regex.IsMatch(textBox2_nume.Text, #"^[ a-zA-Z]+$") == false)
errorProvider1.SetError(textBox2_nume, "Numele contine doar litere si spatii");
else if (textBox3_specialitate.Text == "")
errorProvider1.SetError(textBox3_specialitate, "Introduceti specialitatea medicului");
else
{
try
{
Medic medic = new Medic(Convert.ToInt32(textBox1_cod.Text), textBox2_nume.Text, textBox3_specialitate.Text);
foreach (Medic m in listaMedici)
{
if (textBox1_cod.Text == m.CodM.ToString())
{
throw new Exception("Codul contractului incalca proprietatea de unicitate. Introduceti un cod unic");
textBox1_cod.Clear();
}
}
listaMedici.Add(medic);
listBox1_medici.DataSource = new ObservableCollection<Medic>(listaMedici);
listBox1_medici.DisplayMember = nameof(Medic.NumeM);
listBox1_medici.ValueMember = nameof(Medic.CodM);
listBox1_medici.SelectedIndex = 0;
MessageBox.Show("ADDED!");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
errorProvider1.Clear();
textBox1_cod.Clear();
textBox2_nume.Clear();
textBox3_specialitate.Clear();
}
}
}
private void listBox1_medici_SelectedIndexChanged(object sender, EventArgs e)
{
}
The display member should be the name of the property to display, not a string property. Reflection is used to look for a property of the name of the display member. For example if your medic.NumeM value is "Hello" WPF will look for a property named "Hello", retrieve the value of the property and display it in the listbox.
In your case the code should be: listBox1_medici.DisplayMember = "NumeM";
Related
Background
I have a main form that has a tableLayoutPanel. Within that I have three panel, a header, footer and left side bar. In the remaining space I add and remove usercontrols this one in the example is called ctrlmanagepreset.
Within these usercontrols I have controls. Namely a Listsbox s, that i'm trying to add items too.
I am getting the items from an xml file that does contain items and reading them in to an object list. The name of each object is then added to the listbox.
All of the Controls are accessable as I've made them public. I think it might be due to the way i create and add them?
Question
Why aren't the Listboxes updating, showing the added items?
Code
Button click event that creates usercontrol
public void btnManage_Click(object sender, EventArgs e)
{
tableLayoutPanel.Controls.Add(new ctrlManagePresets () { Dock = DockStyle.Left }, 1, 1);
PopulateCreateJob();
}
Method that Populates Listbox
public void PopulateCreateJob()
{
ctrlManagePresets ctrlmanagepresets = new ctrlManagePresets();
//read in contents of xml file
if (File.Exists(JoblistXmlFilepath))
{
XmlSerializer deserializer = new XmlSerializer(typeof (List<Favourite>));
TextReader reader = new StreamReader(JoblistXmlFilepath);
//create list of old fave objects
var xmlList = (List<Favourite>) deserializer.Deserialize(reader);
reader.Close();
if (xmlList.Count > 0)
{
foreach (Favourite t in xmlList)
{
//add favourite objects to combobox
try
{
ctrlmanagepresets.lbCreateJob.Items.Add(t.Name);
}
catch
{
MessageBox.Show(#"There is an object with no name in the XML.", #"Message",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
}
ctrlmanagepresets.lbCreateJob.Refresh();
}
else
{
ctrlmanagepresets.lbCreateJob.Items.Add(#"Settings File Not Found");
ctrlmanagepresets.lbCreateJob.Enabled = false;
ctrlmanagepresets.lbCreateJob.BackColor = Color.DarkRed;
}
}
You are not adding the items to the instance of the control that you add to your tableLayoutPanel.
Just make your PopulateCreateJob return the instance that is built and intialized with the xml data
public void btnManage_Click(object sender, EventArgs e)
{
ctrlManagePresets ctrl = PopulateCreateJob();
ctrl.Dock = DockStyle.Left;
tableLayoutPanel.Controls.Add(ctrl, 1, 1);
}
public ctrlManagePresets PopulateCreateJob()
{
ctrlManagePresets ctrlmanagepresets = new ctrlManagePresets();
// current code that initialize the instance of your control
....
// return the control instance initialized to the caller
return ctrlmanagepresets;
}
So, I have a project in which I allow editing of a DatagridView in a separate Form. I pass in the DatagridView object and its parent container to the constructor of the new Form.
This works well and I can edit the grid that way. But when I try to give it back by changing its parent back to the original form, I get this error :
Cannot convert type 'System.Windows.Forms.MenuItem' to 'System.Windows.Forms.Control'
Now both MenuItem, and Manual Entry directly inherit from Form.
Here is my code that takes the DataGridView from the original form (which works correctly)
public partial class ManualEntry : Form
{
private Data d;
DataGridView DataView;
MenuItem mi;
public ManualEntry(DataGridView ExcelDisplay, Data d, MenuItem menuItem)
{
InitializeComponent();
//Take the Datagridview from the MenuItem.
DataView = ExcelDisplay;
DataView.Parent = this;
mi = menuItem;
this.d = d;
this.DataView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.DataView.Location = new System.Drawing.Point(15, 76);
this.DataView.Size = new System.Drawing.Size(237, 211);
this.DataView.TabIndex = 5;
this.DataView.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.DataView_CellContentClick);
}
Now here is me trying to give it back. and of course it produces the error above.
private void FinishButton_Click(object sender, EventArgs e)
{
//move the datagridview back to the original form and give its old size,shape, and position back.
DataView.Parent = mi;
this.DataView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.DataView.Location = new System.Drawing.Point(12, 167);
this.DataView.Name = "ExcelDisplay";
this.DataView.Size = new System.Drawing.Size(250, 256);
this.DataView.TabIndex = 7;
this.Close();
}
I have also tried casting which does not work either.
DataView.Parent = (System.Windows.Forms.Control)mi;
Update
This shows that MenuItem is a Form as well.
public partial class MenuItem : Form
{
This shows that MenuItem is a Form as well.
Well, you have not convinced the compiler. You can tell from the error message that it thinks that your "mi" variable is a System.Windows.Forms.MenuItem. Do not use .NET class names for your own types, that just makes your life harder to troubleshoot bugs like this. Don't use variable names like "d" either. Choosing good names is a Very Important programmer's job.
The proper way is to preserve the control's Parent property so you can set it back. Roughly:
public partial class ManualEntry : Form
{
private Data DataViewData;
private DataGridView DataView;
private Point DataViewLocation;
private Control DataViewParent;
public ManualEntry(DataGridView ExcelDisplay, Data data)
{
InitializeComponent();
this.DataViewData = data;
this.DataView = ExcelDisplay;
this.DataViewLocation = ExcelDisplay.Location;
this.DataViewParent = ExcelDisplay.Parent;
this.DataView.Parent = this;
// etc...
}
protected override void OnFormClosing(FormClosingEventArgs e) {
base.OnFormClosing(e);
if (!e.Cancel) {
DataView.Parent = this.DataViewParent;
DataView.Location = this.DataViewLocation;
// etc..
}
}
}
I have a UserControl which I am loading into a div which is inside an UpdatePanel. Here is my code for loading it:
controls.IDLControl IdlControl = LoadControl(#"~/controls/IDLControl.ascx") as controls.IDLControl;
IdlControl.ClientIDMode = ClientIDMode.Static;
IdlControl.ID = "IDLControl";
spGroup.Controls.Clear();
spGroup.Controls.Add(IdlControl);
And here is my code for trying to retrieve an instance of it:
controls.IDLControl IdlControl = RecursiveFindControl(this, "IDLControl") as controls.IDLControl;
private Control RecursiveFindControl(Control targetControl, string findControlId) {
if (targetControl.HasControls()) {
foreach (Control childControl in targetControl.Controls) {
if (childControl.ID == findControlId) {
return childControl;
}
RecursiveFindControl(childControl, findControlId);
}
}
return null;
}
But, all I get is null. I need help on figuring this out.
AFAIK, I need to re-add the control to the page on pre-init but it is one of the controls that can be added depending on which option is selected from a drop down list (which also is filled dynamically). I am stuck trying to figure out how to make this work.
You can try something like this to add your control back in the Page_Init based on the option selected in your DropDownList.
protected void Page_Init(Object sender, EventArgs e)
{
if (IsPostBack)
{
if (drpYourDropDown.Items.Count > 0 && drpYourDropDown.SelectedItem.Text == "yourOption")
{
AddIDLControl();
}
}
}
private void AddIDLControl()
{
controls.IDLControl IdlControl = LoadControl(#"~/controls/IDLControl.ascx") as controls.IDLControl;
IdlControl.ClientIDMode = ClientIDMode.Static;
IdlControl.ID = "IDLControl";
spGroup.Controls.Clear();
spGroup.Controls.Add(IdlControl);
}
I have a class that is a list of class objects.
[Serializable]
public class UserRequestOrders
{
private List<RTORequestOrder> m_thisUsersOrders = new List<RTORequestOrder>();
public List<RTORequestOrder> RequestOrders
{
get { return m_thisUsersOrders; }
set { m_thisUsersOrders = value; }
}
}
When I create an instance of this object I need to populate the list variable When m_thisUsersOrders with an existing list of requests (from a viewstate).
MyOrders.RequestOrders = (List<RTODataEntryObjects.RTORequestOrder>)ViewState["vsMyOrders"];
When the page posts back, I cast the viewstate into a list of RTORequestOrder objects, and try to set the RequestOrders property, I get the message that the property or indexer cannot be assigned to. I have a "SET" accessor for the property.
All posts that I have read on this topic state that I need to modify scope in the application settings, but I am not sure how that applies here. I don't have any application settings set.
I am hoping someone can help me understand how I can populate the list from an existing list.
EDIT: Nico, Thanks for your response! Below is the full code from the code behind page. "MyOrders" and "lst" are essentially the same thing. When I am working with "lst" everything works the way that I want it to. The reason that I want to use the "MyOrders" object instead is because I have a method that returns the list as a datatable with only the fields I need to display. (I didnt' show that code because the issue appears to be with the "SET" accessor.) "lst" has the same signiture as the "MyOrders.RequestOrders". Why can I cast the the viewstate into the lst object, but not the MyOrders object?
EDIT: Grant, thanks for your response as well. I don't know how to set breakpoints for ASP pages... :(
public partial class Default3 : System.Web.UI.Page
{
RTODataEntryObjects.UserRequestOrders MyOrders = new RTODataEntryObjects.UserRequestOrders();
List<RTODataEntryObjects.RTORequestOrder> lst = new List<RTODataEntryObjects.RTORequestOrder>();
void Page_PreRender(object sender, EventArgs e)
{
if (ViewState["vsMyOrders"] == null)
{
NewDataGrid.DataSource = (RTODataEntryObjects.UserRequestOrders)ViewState["vsMyOrders"]; // code to show the data in the grid when page loading
}
}
protected void Page_Load(object sender, EventArgs e)
{
NewDataGrid.EnableViewState = true;
NewDataGrid.DataSource = (RTODataEntryObjects.UserRequestOrders)ViewState["vsMyOrders"];
NewDataGrid.DataBind();
}
public void btnSubmit(object sender, EventArgs e)
{
int id = Int32.Parse(TextBox1.Text); // dynamically getting the data from the frontend.
string name = TextBox2.Text; // dynamically getting the data from the frontend.
if (ViewState["vsMyOrders"] != null) // if the view state is already having data then can update the list and assign again to the viewstate later.
{
lst = (List<RTODataEntryObjects.RTORequestOrder>)ViewState["vsMyOrders"];
MyOrders.RequestOrders = (List<RTODataEntryObjects.RTORequestOrder>)ViewState["vsMyOrders"];
}
RTODataEntryObjects.RTORequestOrder thisOrder = new RTODataEntryObjects.RTORequestOrder(id, name, User.Identity.Name, System.Environment.MachineName);
lst.Add(thisOrder); //
MyOrders.AddNew(thisOrder);
ViewState["vsMyOrders"] = MyOrders;
NewDataGrid.DataSource = (IList<RTODataEntryObjects.RTORequestOrder>)ViewState["vsMyOrders"];
NewDataGrid.DataBind();
}
}
I've created a ListView in a new WPF window and also a function that populates the ListView when it is called. This function just takes the URL of my web server where I've stored the data, increments the "id" and gets the data and stores it in the ListView. Therefore it populates the ListView with a certain number of items.
The problem I'm facing is that I want to add two buttons, ON & OFF, to each ListView item as it gets populated programmatically. i.e, if 16 items are added, I want 2 buttons for each item, and if it's 12 items, the similar procedure. Here's my code:
namespace user_login
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Window1 W = new Window1();
public MainWindow()
{
InitializeComponent();
}
public void populate()
{
int i;
int num = 16;
for (i = 1; i <= num; i++)
{
string val = Convert.ToString(i);
string currentUrl = "http://xpleria.com/devices.php?query=dev&id=";
string newUrlWithChangedSort = ReplaceQueryStringParam(currentUrl, "id", val);
string result = getcontent(newUrlWithChangedSort);
W.list1.Items.Add(result);
}
}
public string getcontent(string URL)
{
string content = "";
// Get HTML data
WebClient client = new WebClient();
try
{
content = client.DownloadString(URL);
}
catch (Exception)
{
System.Windows.Forms.MessageBox.Show("No Connection detected!!!");
}
return content;
}
public static string ReplaceQueryStringParam(string currentPageUrl, string paramToReplace, string newValue)
{
string urlWithoutQuery = currentPageUrl.IndexOf('?') >= 0
? currentPageUrl.Substring(0, currentPageUrl.IndexOf('?'))
: currentPageUrl;
string queryString = currentPageUrl.IndexOf('?') >= 0
? currentPageUrl.Substring(currentPageUrl.IndexOf('?'))
: null;
var queryParamList = queryString != null
? HttpUtility.ParseQueryString(queryString)
: HttpUtility.ParseQueryString(string.Empty);
if (queryParamList[paramToReplace] != null)
{
queryParamList[paramToReplace] = newValue;
}
else
{
queryParamList.Add(paramToReplace, newValue);
}
return String.Format("{0}?{1}", urlWithoutQuery, queryParamList);
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
string user = textbox1.Text;
string password = textbox2.Password;
string currentUrl = "http://xpleria.com/login.php?query=login&user=wcam&pass=wireless";
string newUrlWithChangedSort = ReplaceQueryStringParam(currentUrl, "user", user);
string newUrl = newUrlWithChangedSort;
string FinalUrl = ReplaceQueryStringParam(newUrl, "pass", password);
string result= getcontent(FinalUrl);
string value = result.Substring(0, 8);
string invalid = "xpleria0";
string valid = "xpleria1";
if (value.Equals(invalid))
{
System.Windows.MessageBox.Show("The Username and/or Password you have entered is invalid, please try again");
}
else if (value.Equals(valid))
{
string sessionID = result.Substring(8, 32);
System.Windows.MessageBox.Show("HI, WELCOME CLETA");
this.Close();
using (new user_login.loading.PleaseWait(this.Location))
{
W.Show();
populate();
}
}
}
public System.Drawing.Point Location { get; set; }
}
}
I'm going to recommend you take a step back and start giving some serious consideration to organizing your code. I realize this isn't an answer to the question you asked but it is the answer to the question you should be asking.
First of all, all code relating to the retrieval of these items from the URL should be moved into a class of some kind. This class should accept the URL string as a constructor parameter and gather all the appropriate data. You should then create another class which you will use to populate with the data for each individual item and then expose this list. By the time you're done the code in your window should little more complex than:
var ItemsGetter = new ItemsGetter(URL);
foreach(var Item in ItemsGetter.Items)
{
// Populate the ListView
}
Once you're done with that I recommend you create a UserControl. User controls are extremely useful in situations where you need to represent a dynamic number of data entities each with their own set of controls which allow operations to be performed on each one. You should create a UserControl with a label and the two buttons you need. The UserControl's constructor should expect a parameter of the data type you created to represent each one of your classes. From there you can have the buttons operate on the data type as necessary.
Finally, you'll probably need a way to have the UserControl interact with the Window. Say for example one of your buttons is "Delete". You'd probably want the item to disappear from the list once the operation is complete. Don't be tempted to tie in your control with the Window by passing it as a parameter or something. Instead, read up on Action events and learn how you can create an event on the user control which you bind in the foreach loop of the Window when you're populating the list view. When the UserControl has completed the delete operation triggered by the button you can raise the UserControl's event which will prompt the Window to remove the control from the List View.
Last but not least, NAME YOUR CONTROLS.
Hopefully this helps.