i got a ListView in the windows form.When form loads ListView loading with personel objects. I want to do when some user double clicks on ListView , gets the personel object from the ListView.SelectedItem property and open a new form and transfer this object to newly opened form.
here is my codes for loading personel objects to ListView:
public static void GetAll(ListView list)
{
list.Items.Clear();
using (FirebirdEntityz context = new FirebirdEntityz())
{
ObjectQuery<PERSONEL> query = context.PERSONEL;
foreach (var item in query)
{
var mylist = new ListViewItem { Text = item.NAME };
mylist.SubItems.Add(item.SURNAME);
mylist.Tag = item;
list.Items.Add(mylist);
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
GetAll(listView1);
}
This is my personel object for transfer:
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
PERSONEL personel = (PERSONEL)listView1.SelectedItems[0].Tag;
}
You could probably just add a public PERSONEL property to the form, which you would then set in your SelectedIndexChanged event handler. Then any code that has access to your selector form could access your custom selected PERSONEL property.
In the new form that will be opened, add a new property in the form class;
private PERSONNEL Personnel{get; set;}
public ShowPersonnel(PERSONNEL _personnel){
this.Personnel = _personnel;
//do whatever you want here
}
In the main form;
private void listView1_SelectedIndexChanged(object sender, EventArgs e){
PERSONNEL personnel = listView1.SelectedItems[0].Tag as PERSONNEL;
Form2 form2 = new Form2();
form2.ShowPersonnel(personnel);
form2.Show();
}
May include typos. Change PERSONNEL to PERSONEL.
One way is to have a public propery
as Factor Mystic has suggested.
Or you could have a parametrized ctor
and pass Personnel object. Although,
this might create some problem with
the design view of the form in Visual
Studio.
You should be able to set the display member of the listview control. Berfore you enter the for loop do something like:
list.DisplayMember = "Name"
Then bind the object.
list.DataSource = query.ToList()
The selected item will give you the object you've binded...
MessageBox.Show(((PERSONEL)list.SelectedItem).Name);
This was how it worked in .net 2.0. But I am sure there is probably a way to do this in 3.0 and greater...
Related
I have a child form that displays with a button in user control and I want to clone ListView in user control to its child form.
I checked with breakpoint and printed the list but it gives me error like out of bounds or instance variable is zero.
public partial class JobForm: Form
{
public Job()
{
InitializeComponent();
}
List<string> joblist = new List<string>();
public List<string> _var
{
set {
joblist = value; }
}
}
User Control
private void button_Click(object sender, EventArgs e)
{
//MessageBox.Show(_var[0].ToString());
JobForm jb = new JobForm();
jb.Show();
}
public List<string> listViewJob()
{
_var.Add(item);
return _var;
}
public List<string> _var { get;} = new List<string>();
I used also 'var parent = this.Parent as JobForm; parent.ID2 = ID2; but it gives me same error. So I check with breakpoint it is a correct list until the form shows then I get null or out of bound (_var) in User Control and in Form. I would appreciate if you could write an example.
It is very confusing that both JobForm and the user control have a list called _var. Its best to use more descriptive variable names.
I'm not completely sure what you want to achieve, but basically, when you have created the child form you can access its properties.
For instance:
private void button_Click(object sender, EventArgs e)
{
//MessageBox.Show(_var[0].ToString());
JobForm jb = new JobForm();
// Members of 'jb' are available here
this._var = jb._var;
jb.Show();
}
I have a windows form that allows different user controls to show and be hidden by different button.
I would like this user controls to communicate directly with each other and change values etc.
For example usercontrol1 below
User will fill form, then when they click Proceed, usercontrol1 should close and usercontrol2 should now be visible with user information picked and displayed as follows
So far I have the code below
private void btnProceed_Click(object sender, EventArgs e)
{
string name = tbName.ToString();
string email = tbEmail.ToString();
string phone = tbPhone.ToString();
string color = tbColor.ToString();
this.Hide();
UserControl2 u2 = new UserControl2();
MainForm f1 = new MainForm();
f1.panelMain.Controls.Add(u2);
f1.listView1.Items.Add(new ListViewItem(new[]{
name,
email,
phone,
color}));
}
It does not work. Only the usercontol1 is hidden and I'm left with a blank.
What I'm I doing wrong?
(Using visual studio 13 and c# language)
You are adding the new usercontrol to a new instance of MainForm. You can't see it because this new instance is never shown. To avoid this problem in the simplest possible way you pass the instance of the current MainForm to the UserControl constructor, keep that instance stored in a global variable of the UserControl and use that instance when you need to switch the two usercontrols.
In MainForm.cs (when you create the first usercontrol)
UserControl1 uc = new UserControl1(this);
.....
In UserControl1.cs
public class UserControl1
{
MainForm _current;
public UserControl1(MainForm f)
{
InitializeComponent();
_current = f;
}
private void btnProceed_Click(object sender, EventArgs e)
{
.....
UserControl2 u2 = new UserControl2();
_current.panelMain.Controls.Add(u2);
u2.listView1.Items.Add(new ListViewItem(new[]{
name,
email,
phone,
color}));
}
}
This will be problematic to correctly handle for other tasks. I would recommend to redesign your application to let the MainForm decide which usercontrol to show when needed.
In this approach you use events to get informed in MainForm.cs when the user clicks the UserControl1, so you get this in MainForm.cs
UserControl1 uc = new UserControl1();
uc.UserClick += UserAdded;
.....
where UserAdded is a method of MainForm that received the info about the new user though the class UserInfoArgs
public void UserAdded(UserControl1 sender, UserInfoArgs args)
{
sender.Hide();
UserControl2 u2 = new UserControl2();
this.panelMain.Controls.Add(u2);
u2.listView1.Items.Add(new ListViewItem(new[]{
args.name,
args.email,
args.phone,
args.color}));
}
And in UserControl1 you add the delegate, the event and raise the event when you need to communicate to MainForm the info about your new user.
public class UserControl1
{
public delegate void onClick(UserControl1 sender, UserInfoArgs args);
public event onClick UserClick;
....
private void btnProceed_Click(object sender, EventArgs e)
{
UserInfoArgs args = new UserInfoArgs()
{
name = tbName.Text,
email = tbEmail.Text,
phone = tbPhone.Text,
color = tbColor.Text
};
if(UserClick != null)
UserClick(this, args);
}
public class UserInfoArgs
{
public string name {get;set;}
public string email {get;set;}
public string phone {get;set;}
public string color {get;set;}
}
I think using backgroundworker control for this actually works for your case .
private void btnProceed_Click(object sender, EventArgs e)
{
string name = tbName.ToString();
string email = tbEmail.ToString();
string phone = tbPhone.ToString();
string color = tbColor.ToString();
string a = " "+name+" "+email+" "+phone+" "+color;
backgroundWorker1.RunWorkAsync(a);//passing the variables to the backgroundWorker
}
And then in backgroundWorker_doWork(),you can populate the data you're getting as you like .
You are overcomplicating things. You can just layer the two controls on your UI on the same position, and set the second control's Visible property to False.
Make the first user control expose an event for the button's click (or just expose the button so you can access its Click event), so that you can detect that mouse click from the main form. Then, when the listener for that button is called; the main form can get the data out of the first control, use it to initialize the second control, and then hide the first one and show the second one.
Suppose i have created a WPF form having one text box. i am calling that form inside another wpf window's gridpanel and after entering value inside the textbox, i am clicking on submit button. After button click, i need to get that value and save it in string form inside my current class. My logic is something like this.
For getting the from inside my current window:-
void SelectedClick(object sender, RoutedPropertyChangedEventArgs<object> e)
{
selectedItem.ContextMenu = VcontextMenu;
VcontextMenu.Items.Add(VmenuItem1);
VmenuItem1.Click += AddValidation;
details();
}
void AddValidation(object sender, RoutedEventArgs e)
{
ValidationForm obj = new ValidationForm();
ProcessGrid.Content = obj.VForm;
}
Now i want to store the value of my textbox inside a string. For that i have used following code:-
public void details()
{
ValidationForm obj = new ValidationForm();
string str = obj.s.ToString();
}
My ValidationForm Code:-
public partial class ValidationForm : UserControl
{
public string s { get; set; }
public ValidationForm()
{
InitializeComponent();
}
public void XSave_Click(object sender, RoutedEventArgs e)
{
s = TextValidationName.Text;
}
}
but instead of opening the form, the control is going to obj.s.ToString() and showing error as "Object reference not set to an instance of an object." Please help. Thanks.
The issue is caused since the string s in your ValidationForm class is not assigned. It is probably caused since the XSave_Click() method is not being called.
Ensure that you properly assign the value to s before you try to get value from it.
Im running into a bit of an issue regarding Children and parents.
I have 2 forms which have the same dropdown menus, both of which have the ability to add additional options to them. When the "(add new)" option is selected in any of the combo boxes my third form is loaded which enables the addition of a new option.
This is the code for that third window (as it stands)
public partial class taskNewDropdownEntry : Form
{
taskWindow _owner;
applianceWindow _owner2;
int windowType;
int manufacturer_id;
sqlMod data = new sqlMod();
public int setManufacturerID {get { return manufacturer_id; } set { manufacturer_id = value; } }
public taskNewDropdownEntry(taskWindow owner, int type)
{
InitializeComponent();
this._owner = owner;
this.windowType = type;
}
public taskNewDropdownEntry(applianceWindow owner, int type)
{
InitializeComponent();
this._owner2 = owner;
this.windowType = type;
}
private void taskNewDropdownEntry_Load(object sender, EventArgs e)
{
if (windowType == 1)
{
instructionLabel.Text = "Input the new appliance type below";
}
else if (windowType == 2)
{
instructionLabel.Text = "Input the new manufacturer below";
}
else if (windowType == 3)
{
instructionLabel.Text = "Input the new model below";
}
}
private void btnOK_Click(object sender, EventArgs e)
{
if (windowType == 1)
{
data.insertApplianceType(textField.Text);
_owner.refreshTypeCombo();
}
else if (windowType == 2)
{
data.insertManufacturerSimple(textField.Text);
_owner.refreshManuCombo();
}
else if (windowType == 3)
{
data.insertModelSimple(manufacturer_id, textField.Text);
_owner.refreshModelCombo();
}
this.Close();
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
}
}
Now, my issue is that the 2 forms that call this third form are different - thus my only thought of how to solve this would be to duplicate some of the code and modify the methods (you can see the second constructor already added).
Instead of having multiple constructors, and duplicated methods (in this class, or in a seperate one) is there a way whereby I can use the same constructor but different owners depending on the form that calls it?
You have too much implementation in your child form. The way I would tackle this is to
Add a property to your child form:
public string InstructionLabel { get; set; }
This allows your parent forms to individually set the label text when instantiating the form, and also set up an event handler for when the form is closing. So your parent form would have code something like
var newItemForm = new taskNewDropdownEntry();
newItemForm.InstructionLabel = "Input the new appliance type below";
newItemForm.FormClosing += new FormClosingEventHandler(ChildFormClosing);
Then somewhere early in your child form's life cycle (FormLoading event) set
instructionLabel.Text = InstructionLabel;
Then also add a property in the child form for
public string NewItem { get; set; }
your child form should set this public property in the btnOK_Click event
private void btnOK_Click(object sender, EventArgs e)
{
this.NewItem =textField.Text;
}
Then your parent form listens for a FormClosing event, and when it hits that event it takes the NewItem text, adds it to the relevant combo and refreshes it. So in the parent form, the handler looks like
private void ChildFormClosing(object sender, FormClosingEventArgs e)
{
sqlMod data = new sqlMod();
data.insertApplianceType(textField.Text);
refreshTypeCombo();
}
Pretty hard to understand the question but code speaks for all.
There are 2 options, worse (because keeping the parent reference is not a good practice first of all):
create an interface that both classes taskWindow and applianceWindow (where is the naming convention for god's sake!) implement, ex
intrerface IRefreshable {
void refreshManuCombo();
}
then constructor and your poperty can have type of IRefreshable
IRefreshable _owner;
public taskNewDropdownEntry(IRefreshable owner, int type)
{
InitializeComponent();
this._owner = owner;
}
better option, use child form events like Closed to implement refreshing logic in parent. You just need to register event handler before showing the form and voila. Check examples here:
https://msdn.microsoft.com/en-us/library/system.windows.forms.form.closed(v=vs.110).aspx
You can also implement your own public form event for more custom usage (ex. DataChanged, ResultGenerated).
I have a listbox full of items for my order.
I want to take all of the items inside my listbox and transfer them into my listview.
Then I want to take my listview and display it in another form (my messagebox).
My new listview:
private void CustomerInfo_Click(object sender, EventArgs e)
{
ListViewItem customers = new ListViewItem(fullName.Text);
customers.SubItems.Add(totalcount.ToString());
customers.SubItems.Add(total.ToString());
customers.SubItems.Add(Address.Text);
customers.SubItems.Add(telephone.Text);
for (int i = 0; i < OrderlistBox.Items.Count; i++)
{
customers.SubItems.Add(OrderlistBox.Items[i].ToString());
}
Customers.Items.Add(customers);
//CLEAR ALL FIELDS
OrderlistBox.Items.Clear();
fullName.Text = "";
Address.Text = "";
telephone.Text = "";
totalDue.Text = "";
totalItems.Text = "";
}
My contextMenuStrip, so when I click on the customer I can get its info (name, address, order, etc.):
private void customerInformationToolStripMenuItem_Click(object sender, EventArgs e)
{
if (Customers.SelectedItems.Count != 0)
{
var myformmessagedialog = new MessageBoxForm
{
name = Customers.SelectedItems[0].SubItems[0].Text,
address = Customers.SelectedItems[0].SubItems[3].Text,
telephone = Customers.SelectedItems[0].SubItems[4].Text,
};
myformmessagedialog.ShowDialog();
}
}
My new form, the messagebox where I will display all the info for the client:
public partial class MessageBoxForm : Form
{
public MessageBoxForm()
{
InitializeComponent();
}
public string name;
public string address;
public string telephone;
public ListViewItem order = new ListViewItem();
private void MessageBoxForm_Load(object sender, EventArgs e)
{
lblName.Text = name;
lbladdress.Text = address;
lbltelephone.Text = telephone;
orderListView.Items.Add(order);
}
}
I'm sorry if this seems confusing but I'm just looking for help to go in the right direction. Any help is appreciated.
One way to do this is to put the data that you want to display in some sort of ViewModel, basically a class or set of classes that has the data that you want to display. Then the main form can display it, and you can pass a reference to that ViewModel to the message box and it can display it as well.
In general you want to avoid any kind of code that directly ties controls from different forms together.
The easiest way based on your current setup is to simply pass your list view data across to your MessageBoxForm e.g.
public partial class MessageBoxForm : Form
{
...
public void LoadListView(ListViewItemCollection items)
{
orderListView.Clear();
orderListView.AddRange(items);
}
}
....
private void customerInformationToolStripMenuItem_Click(object sender, EventArgs e)
{
if (Customers.SelectedItems.Count != 0)
{
var myformmessagedialog = new MessageBoxForm
{
name = Customers.SelectedItems[0].SubItems[0].Text,
address = Customers.SelectedItems[0].SubItems[3].Text,
telephone = Customers.SelectedItems[0].SubItems[4].Text,
};
myformmessagedialog.LoadListView(Customers.Items);
myformmessagedialog.ShowDialog();
}
}
Basic answer is you don't.
You maintain a collection of items (whatever they are).
You display them in a list box.
You display them in a list view.
If you want say select some from the list box and only move them to the list view.
Then you use the listbox selection to find them in your collections of items, create a list of selected ones then passs that to the form with the listview to display.
Don't use UI controls to store your data and try really hard to never make one form's UI directly dependant on another.
I'm guessing what you'd need (and I could have misunderstood what you are looking for) is a new method in you MessageBoxForm to pass in your Customers object:
private void customerInformationToolStripMenuItem_Click(object sender, EventArgs e)
{
if (Customers.SelectedItems.Count != 0)
{
var myformmessagedialog = new MessageBoxForm;
myformmessagedialog.Customers = Customers;
if (myformmessagedialog.ShowDialog() == DialogResult.OK)
{
Customers = myformmessagedialog.Customers;
}
}
}
If so, simply modify your class to be something like this:
public partial class MessageBoxForm : Form
{
public MessageBoxForm()
{
InitializeComponent();
}
private void MessageBoxForm_Load(object sender, EventArgs e)
{
if (Customers != null)
{
// add your code here to add your Customers as needed
}
}
public Customers Customers { get; set; }
}
To access anything from the parent form you need to pass it to the child form so
myformmessagedialog.ShowDialog();
becomes
myformmessagedialog dialog = new myformmessagedialg(this);
dialog.ShowDialog();
and your class constructor becomes this:
public MessageBoxForm(myformmessagedialog parent){
name=parent.fullName.Text;
address=parent.address.Text;
...etc...
InitializeComponent();
}
Though it might be better to just pass in the name, address, etc rather than the whole form, this way is nice for while you are changing things because you have one less place to change to add another variable to pass.