I have written a property in a user control class using set get like this :
public partial class MyUserControl : UserControl
{
public string ServerName { get; set; }
public PagingUserControl()
{
InitializeComponent();
}
}
then by adding this user control to a windows form project I set ServerName in the "Misc" section of properties window.
now here is the question, how can I access ServerName from another usercontrol ? I think I should access the property "ServerName" of the object made by the constructor of "MyUserControl"
The right approach is to reverse the data flow by extracting your model being the value of the ServerName property out of the user control and bind both user controls to it, see Windows Forms Data Binding for details. This way you can save a lot of time on plumbing and passing data between your components.
If you are specifically looking for how to implement this with your existing code then following steps below may be able to help you too. Once you drop an instance of the user control to the form, the designer is going to generate some code for it in the Form1.Designer.cs file.
// the declaration of your user control
private MyUserControl1 myUserControl11;
private void InitializeComponent()
{
// the initialization of your user control
this.myUserControl11 = new WindowsFormsApp3.MyUserControl1();
}
This code makes it possible to access the instance of the user control from the form. If you are asking how to share the value of this property with another control you would need to implement INotifyPropertyChanged inside your user control.
public partial class MyUserControl1 : UserControl, INotifyPropertyChanged
And then subscribe your parent form to this event.
private void InitializeComponent()
{
// subscribe to the user control event
this.myUserControl11.PropertyChanged +=
new System.ComponentModel.PropertyChangedEventHandler(
this.myUserControl11_PropertyChanged);
}
// handle the event by updating the other control
private void myUserControl11_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
textBox1.Text = myUserControl11.ServerName;
}
Once you have notification implemented you may consider looking at how data binding can be used to achieve the data propagation between controls with less code. Hope it helps!
Related
What I want is to store a method with parameters owned by one class in a variable in another class for later execution. The first class would be my MainWindow class and second is a UserControl. The method I want to pass would stand in as a SelectionChanged event for a ListBox contained in the UserControl. The method would require a parameter only the UserControl will know at the time items are changing.
An example for my method (in MainWindow) would be as follows:
public void MethodToPass(string UniqueParameterValue) {
//...do stuff with special string
}
And I would pass the method in my MainWindow class like:
//In MainWindow.Loaded
this.userControlInstance.SelectionChanged += MethodToPass;
Because I'm not directly assigning it to the ListBox, I would do so in the UserControl like:
private void selectionChanged;
public void SelectionChanged {
get {
...
}
set
{
this.selectionChanged = value;
this.listBox1.SelectionChanged += value;
}
}
I feel like NOT directly setting the ListBox is redundant, but my MainWindow class does not allow me to "see" it. I also feel like the more politically correct way to do this is to store the method in a variable, but I don't know how to do that or call it.
How are operations like this usually done?
You should be able to expose the properties of your user control by creating them as class properties as usual. Then you can create an event on your user control which is raised by the SelectionChanged event of your ListBox. You can subscribe to this event using a delegate on your main window.
Check out these links:
How to access properties of a usercontrol in C#
How do I make an Event in the Usercontrol and Have it Handeled in the Main Form?
I have a custom control that I'm also using as a DataGridView control. This custom control has a method called SetHttpClientand I pass a HttpClient object as parameter.
How can I call this method from the parent form? (The parent form only knows about the instance of the class deriving from DataGridViewTextBoxCell)
You should build a nice structure for this. For example if you have two Forms, and in Form 1 you have the Grid, which you want to refresh From Form 2. If you want to open Form 2, you should pass the instance of the Grid from on creating the instance.
Or a second way, Form 2 provide an event which will be subscribed in Form 1. And the event is called if the Grid should be refreshed. You can than pass the HttpClient over the Args-Object to Form 1.
Please tell me, if i misunderstand you.
In my opinion you should use a ViewModels to communicate with View instead of one View execute action on second View.
So, for example your View like
CustomersView contains CustomersViewModel in DataContext, if you execute a operation GetData you make it in CustomersViewModel and the result put to DataGridView.
This solution moves responsibility of providing data from class DataGridView to CustomersViewModel. The ViewModel can use some Service or other mechanism to provide you data using HttpClient.
I know that's not straight answer for your question, but is good solution for your problem.
In this example https://msdn.microsoft.com/en-us/library/ff798384.aspx you have method GetParts, you can imagine that the body of this method contains HttpClient and get the data from a website.
May be you're talking about access modifiers like private, public, internal.
If so, then in child form make access modifier like public or internal.
And in parent form just make needed call.
public partial class ChildForm : Form
{
public ChildForm()
{
InitializeComponent();
}
internal String HellowWorld_mt(string SuffixValue)
{
return "hello world and "+ SuffixValue;
}
}
public partial class ParentForm : Form
{
public ParentForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ChildForm cf = new ChildForm();
cf.Show();
string resp = cf.HellowWorld_mt(" extra!");
this.Text = resp;
}
}
More about that: Access Modifiers (C# Reference)
I am currently working on a Winforms solution where I have a Main Form containing a ToolStrip and a Panel. The solution is meant as an administrative tool.
The panel is filled with a user control, normally containing an input form or a ListView of some sort.
Depending on which button is clicked the user control in the Panel is replaced with another user control.
So far so good. Now the trickier part is that the user can be administrator of one or more departments, and if the user is admin of more than one departments, some of the user controls will be displaying a ComboBox where the admin can choose which department to admin. However some of the user controls are independent of the department and therefore does not contain the ComboBox.
Now the thing is that instead of adding the ComboBox to the user control that are department-specific I have been thinking about adding it to the Main Form and have the user controls, when instantiated, look at what department is picked and populate the data accordingly.
But my problem is: When a user then is picking another department in the ComboBox I will have to tell the child (user control) that the value has changed.
My first thought was to have the user control - when instantiated - sign up for the change-event. But that I can not seem to figure out how to get working (it is easier going the other way around).
Another approach that I have been thinking about is to call a method in the user control from the Main Form whenever the value has changed. However there will be no guarantee that such method exists as not all user controls need this functionality.
Is there a preferred/golden solution to this? Something I am missing or is this just bad practice/design?
Thanks in advance!
When childcontrols needs to be notified, i would implement an Interface. You should avoid crosscalling methods/event handling because events could lead to "ghost controls" and unreadable code.
I would do something like this: (pseudo/not tested)
public interface IDepartmentChanged
{
void DepartmentChanged(int departmentId);
}
public class UserControl1 : UserControl, IDepartmentChanged
{
public void DepartmentChanged(int departmentId)
{
// refresh data
}
}
public class Form1 : Form
{
// Add all UserControls to a List => _controls
private List<UserControl> _controls = new List<UserControl>();
public Form1()
{
InitializeComponent();
_controls.Add(userControl11);
}
private void comboBox1_SelectedValueChanged(object sender, EventArgs e)
{
int selectedDepartmentId = ((MyData)comboBox1.SelectedValue).Id;
foreach (UserControl control in _controls)
if (control is IDepartmentChanged)
((IDepartmentChanged)control).DepartmentChanged(selectedDepartmentId);
// or even shorter:
foreach (IDepartmentChanged departmentChanged in _controls.OfType<IDepartmentChanged>())
departmentChanged.DepartmentChanged(selectedDepartmentId);
}
On this method the childs functionality is totally separated from the parent.(OOP)
i created a form and a userenter code hereControl (called UserControl1) and added it to the form. i've added a comboBox to the form and then did:
public Form1()
{
InitializeComponent();
comboBox1.SelectedValueChanged += userControl11.comboBox1_SelectedValueChanged;
}
and then when the comboBox1 the user control knows about it and can re initiate
I have designed custom user control in c# .This user control is include :
textbox,check box,button.
Now I want to consume designed user control in my project but the problem is I can't access to the textbox,checkbox,button EVENTS when consume user control in my form and there are only EVENTS for user control.how can I make it possible that each object events become accessible when consuming designed user control ?
In your user control set your control like "text-box" Modifiers property to Public.so when you add this user control to your form. you can access to your text box evens:
public Form1()
{
InitializeComponent();
userControl11.textBox1.TextChanged += new EventHandler(textBox1_TextChanged);
}
void textBox1_TextChanged(object sender, EventArgs e)
{
MessageBox.Show("user control textbox.text changed");
}
you might need to manually create public events for the events of those controls which you want to be accessible from outside.
another way is, when initializing those controls in you user control, using public instead of private (which is automatically generated by VS), these code should be located in the xxx.Designer.cs, and they looks likeprivate System.Windows.Forms.Button button1. Then it can be accessed through MyUserControl.button1. But doing so, the entire control will be accessible from outside of your user control, which does not feel very well personally.
I think you should add public events to your custom control class, and make subscribing and unsubscribing there. Just like that:
public event EventHandler ComboboxClick
{
add { _combobox.Click += value; }
remove { _combobox.Click -= value; }
}
For more information see http://msdn.microsoft.com/en-us/library/8627sbea(v=vs.71).aspx
Edit: I would not recomend setting inner controls of your custom control as public properties, because it's a violation of encapsulation principle. You design your own control to do some specific job and clients of the control should stay unaware of its inner composition. Should you change the inner composition of your control in future (switch to some 3rd party textbox control, for example), you would only need to make changes in your custom control class, and its clients would still work properly as if nothing has happend. Here's a good koan about encapsulation =)
I have an issue when it comes working with events and/or delegates. I saw very similar questions but still the real implementation is not clear to me. So please when you answer be more specific so I can try and eventually understand how exactly creating/handling of public/custom events work by doing it in a code I know.
What I have is a User Control which is simply a text box and a button I need to change a record in a database using the value from the text box. I'm using this control for many forms so I need to know which entity exactly I'm using and be able to call it's own save method. Doing all that will be easier if I just can use the click event of the button from my User Control and then call the Save() method of the current form.
This is my User Control :
namespace UserControls.CommonControls
{
public delegate void ClickMe(string message);
public partial class ChangeCode : UserControl
{
public event ClickMe CustomControlClickMe;
public ChangeCode()
{
InitializeComponent();
}
private void btnChange_Click(object sender, EventArgs e)
{
if (CustomControlClickMe != null)
CustomControlClickMe("Hello");
//ToDo fill
//MessageBox.Show("To Do: Write the busieness logic.");
}
public void SetTextBoxMask(MaskedTextBox txtBox)
{
txtChange.Mask = txtBox.Mask;
}
}
}
I post it with the last attempt I made to try and implement what I need.
This is one of the form that need to use the Click event from the User Control and more specific the Constructor because if I understand right there is the place where I have to subscribe for the event :
public MaterialEdit()
{
InitializeComponent();
UserControls.CommonControls.ChangeCode. += new ClickMe(button2_Click);
}
UserControls.CommonControls.ChangeCode - this is how I reach my User Control it's named ChangeCode.
From what you pasted it is not clear that you added ChangeCode control to your form. To use the control and it's events and properties, first you must create new instance to it and add it to the form. This is done:
In designer, by dragging control from Toolbox to the form
In code editor, by invoking control constructor and adding new object to control collection
Only then can you handle event of that object. Let's say that you dropped ChangeCode control to a form, and that Visual Studio named it ChangeCode1. You attach a handled to CustomControlClickMe event like this:
ChangeCode1.CustomControlClickMe += new ClickMe(button2_Click);
Code you pasted (UserControls.CommonControls.ChangeCode. += new ClickMe(button2_Click);) is incorrect for several reasons:
Syntactically, left hand side expression ends with . which makes it incorrect assignment target (UserControls.CommonControls.ChangeCode.)
Event name is not provided, only the control name (you need to end left hand side of assignment with what you want to assign to - .CustomControlClickMe)
You are trying to attach handler to a class and not an object