Pass Value Selected From a User Control to a Parent - c#

I have a Winform dialog that contains several user controls - all of them are some sort of Datagridview. The main parent has details about a user, and the user controls each have additional details on that person. When my Dialog first loads all of the UserControls work but I am trying to figure out how to update the UserControl2 based on a position change in UserControl1.
So, I am trying to select a row in UserControl1 and have the data in UserControl2 update based on a value that I just selected.
I have tried using MouseDownEvents on the UserControl1 and BindingSourcePositionChanged but I can't figure out how to get the value selected back to my parent form and then use that value to refresh the other datagrids?
I looked at delegates and events but I guess the lack of sleep is making it incredibly hard to comprehend. I understand that I need to create my delegate and event on the UserControl1 and then somehow call it on my mainform but that's where I get stuck and have no clue where to start.
Is this the right direction? Or is there another way to get this done? Can anyone offer up any suggestions on how this works?

Yes this is the correct approach something like the following will provide an event handler that you can use to the retrieve a public property from the UserControl:
public class SomeClass : BaseControl
{
public event EventHandler PersonSelected;
public string Name{get;set;}
protected void FindUser()
{
var find = new Button {ID = (ToString() + "search"), Text = "Search"};
find.Click += delegate(object sender, EventArgs e)
{
if (PersonSelected!= null)
{
//forward this event to the page's event handler
PersonSelected(this, e);
}
};
}
}
public class SomeOtherClass : Page
{
public void Main()
{
var sp = (SomeClass)Control;
sp.PersonSelected += BtnClick;
}
public void BtnClick(object sender, EventArgs e)
{
//Get some value from the (SomeClass)Control here
}
}

Related

Windows Forms C#: Access TabControl from UserControl

I have a TabControl and a UserControl interacting in the following way:
Each time a new tab is opened, the UserControl loads onto the new tab.
In the UserControl there's a Panel, a TexBox and a Button. Each time text is entered into the TexBox and the Button is pressed, it's supposed to update the title of the current tab
How do I access the tab title from within the UserControl?
Better if the user control does not know where it is embedded into.
Consider providing a TitleChanged event in the user control instead. Then it can be the responsibility of the consumer to update itself accordingly.
public class MyUserControl : UserControl
{
// [...]
public string Title { get; private set; }
public event EventHandler TitleChanged;
// [...]
private void MyTextBox_TextChanged(object sender, EventArgs e)
{
Title = MyTextBox.Text;
TitleChanged?.Invoke(this, EventArgs.Empty);
}
}
And the necessary code of the consumer class can be sg like this:
// after subscribing the myUserControl.TitleChanged event:
private void MyUserControl_TitleChanged(object sender, EventArgs e)
{
myTab.Text = myUserControl.Title;
}
Even better if you use data binding in the user form:
myTab.DataBindings.Add(nameof(TabPage.Text), myUserControl, nameof(MyUserControl.Title));

Enabled button in a form through access control [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Get access to parent control from user control - C#
I have btnMessage on my form Main, and I also have user control (uc).
When I click btnMessage, it opens the uc and also makes btnMessage.enabled = false. In uc, there's a button that's called btnExecute.
What I want is that when I click on btnExecute in uc, btnMessage in Main form will be disabled. How I can do this?
Here's the update code :
I'm using function in main.cs
public Main()
{
InitializeComponent();
formFunctionPointer += new functioncall(buttonHideorEnabled);
ucMessageTarget.userFunctionPointer = formFunctionPointer;
}
public delegate void functioncall(bool _status);
private event functioncall formFunctionPointer;
public void buttonHideorEnabled(bool _status)
{
btnMessageTarget.Enabled = _status;
}
and in uc.cs :
public static string agentName = UtilitiesToolkit.agentMessageTarget;
public static string strn;
public UcMessageTarget(string str)
{
InitializeComponent();
strn = str;
}
public Delegate userControlPointer;
public Delegate userFunctionPointer;
private void btnExecute_Click(object sender, EventArgs e)
{
btnExecute.enabled = false;
userFunctionPointer.DynamicInvoke(false);
//I want btnMessage in Main form also disabled, please tell me how
}
but, still, didn't work. when I compile, I have error in main, in this line :
public Main()
{
InitializeComponent();
formFunctionPointer += new functioncall(buttonHideorEnabled);
ucMessageTarget.userFunctionPointer = formFunctionPointer;
}
said, that
object reference is not set to an instance of object (in
ucMessageTarget.userFunctionPointer = formFunctionPointer;).
please help.
You can programmatically subscribe to event handlers in the code-behind, so add one to the "parent" form for the "child" form's button:
uc.btnExecute.Click += new EventHandler(name_of_method_to_handle_click_event);
The only requirement is that the control be public so that the parent form can access it.
What I would rather do is raise an event from the user control, which the main form listens to, and then disable the button in this event handler.
Something like User Control Events in VB and C#
This would avoid the user control having to "know" anything about the caller (parent form).
Search a little on SO, you will find a lot of examples for raising events from user controls.

How to pass textbox data between two forms?

How to send textbox value to textbox between two forms without Show()/ShowDialog() by button?
I want to textBox will get value without open form.
To access the textbox data you need to use: textBox1.Text
a form is an object so you can define a method that updates the text box value (you can expose the textbox itself with a public accessor)
To pass information from a parent from to a child form you should create a property on the child form for the data it needs to receive and then have the parent form set that property (for example, on button click).
To have a child form send data to a parent form the child form should create a property (it only needs to be a getter) with the data it wants to send to the parent form. It should then create an event (or use an existing Form event) which the parent can subscribe to.
An example:
namespace PassingDataExample
{
public partial class ParentForm : Form
{
public ParentForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ChildForm child = new ChildForm();
child.DataFromParent = "hello world";
child.FormSubmitted += (sender2, arg) =>
{
child.Close();
string dataFromChild = child.DataFromChild;
};
child.Show();
}
}
}
namespace PassingDataExample
{
public partial class ChildForm : Form
{
public ChildForm()
{
InitializeComponent();
}
public string DataFromParent { get; set; }
public string DataFromChild { get; private set; }
public event EventHandler FormSubmitted;
private void button1_Click(object sender, EventArgs e)
{
DataFromChild = "Hi there!";
if (FormSubmitted != null)
FormSubmitted(this, null);
}
}
}
I don't know what exactly you mean by saying "without Show()/ShowDialog()", but that is not relevant anyway or I'll just assume here further that you have both windows open (doesn't matter how you accomplished that).
You would like to avoid much coupling between two forms, especially not implementation details like a textbox etc. You could work with delegates and events to trigger the "sending" of data between your two forms. You can then easily pass event data and your subscribed other form (or any other object as a matter of fact) doesn't know the exact implementation details of your form, it only knows the data it will receive through the delegate (event). I am not going to post all code here, because it is already nicely explained at following URL: http://www.codeproject.com/Articles/17371/Passing-Data-between-Windows-Forms .

C# User Control - How to tell containing object the control needs data

I am creating a C# WinForms user control. There will be times when the user control will need data from the form it's contained in. How do I go about having the user control tell the form containing it that it needs some data?
Thanks!
You can subscribe the form to an event raised on the UserControl.
Your archiecture dictates where and when you need to subscribe to the data event. We can't answer that without knowing a little more about how your whether you are adding the control at runtime or design time. Each case will require a little derivation. From the perspective of adding your control at runtime, you could do something similar to the following:
// Your sample control
public class MyUserControl : Control
{
public event EventHandler<EventArgs> INeedData;
public Data Data {get; set;}
private class DoSomething()
{
if(INeedData!=null) INeedData(this,null);
}
}
...
// Your Form, in the case that the control isn't already added.
var _myUserControl = new MyUserControl();
private void Form1_Load(object sender, EventArgs e)
{
_myUserControl.INeedData += new EventHandler<EventArgs>(MyUserControl_INeedData);
this.Controls.Add(myUserControl);
}
void MyUserControl_INeedData(object sender, EventArgs e)
{
_myUserControl.Data = SomeData;
}
Create a custom event in the user control and have the form hook into it. If you need custom event arguments, you can create those too.
In user control:
//Define your Custom Event argument
public class MyEventArgs : EventArgs
{
//Define some fields of your custom event argument
private int m_SomeValue = 0;
//Define some properties of your custom event argument
public int SomeValue
{
get { return m_SomeValue; }
set { m_SomeValue = value; }
}
}
//Define the event handler data type
public delegate void MyEventHandler(object sender, MyEventArgs e);
//Define the object which holds the outside event handlers
public event MyEventHandler SomeEvent;
//Define the function which will generate the event
public virtual void OnSomeEvent(MyEventArgs e)
{
if (SomeEvent != null)
SomeEvent(this, e);
}
.
. //Then later in the control
.
{
//We need new data
//Create the event arguments
MyEventArgs newEvent = new MyEventArgs();
//Set the values
newEvent.SomeValue = 17;
//Call the event generating function
OnSomeEvent(newEvent);
}
In your form just use something like:
myControl.SomeEvent += new MyEventHandler(handlerName);
Since your event is public, you should see it in the Properties window of your control as well.
You can fancy up the event using Metadata attributes, but I leave it up to you to discover these.
Create an event on the user control where the event args are editable. Let the form attach a handler to that event, which updates those fields. Use those fields in the OnEvent method.
[untested]
eg.
public delegate void NeedsUserDataEventHandler(object sender, NeedsUserDataEventArgs args);
public class NeedsUserDataEventArgs : EventArgs
{
public UserData UserData { get; set; }
}
// In Control
public event NeedsUserDataEventHandler NeedsUserData;
public void OnNeedsUserData(NeedsUserDataEventArgs args)
{
NeedsUserDataEventHandler handler = NeedsUserData;
if (handler != null) handler(this, args);
// store your data somewhere here
}
// In Form
public override void OnLoad(object sender, EventArgs args)
{
control.NeedsUserData += ControlNeedsUserData;
}
public override void OnClosed(object sender, EventArgs args)
{
control.NeedsUserData -= ControlNeedsUserData;
}
public void ControlNeedsUserData (object sender, NeedsUserDataEventArgs args)
{
args.UserData = // set whatever here
}
Seems a bit vague to me, but:
Make it an event in the containing WinForm, so that every time some data is ready all the subscribers can be notified in a one-to-many model; or make it an event in the subscribed control, in a one-to-one model, in which it calls the container's method that retrieves such data?
It's dependent on when that data needs to be pushed to the UserControl. Are there events taking place on the Form that will drive the need to move data within the UserControl? If so...simply grab your instance at that point and push the data down to the UserControl via a public property.
If this is a case where events are not being used or the Form in some fashion or another "receives the data" then exposing an event on the Form such as...
public event DataHandler ReceivedData;
...and allow the UserControl or any other container to register for the event and receive the data via your custom event args. Pushing the event into the UserControl and forcing the Form to latch onto the UserControl seems backwards since the Form is the initiator of the data.

Sending string from class to Form1

Although there are some similar questions I’m having difficulties finding an answer on how to receive data in my form from a class.
I have been trying to read about instantiation and its actually one of the few things that does make sense to me :) but if I were to instantiate my form, would I not have two form objects?
To simplify things, lets say I have a some data in Class1 and I would like to pass a string into a label on Form1. Is it legal to instantiate another form1? When trying to do so it looks like I can then access label1.Text but the label isn’t updating. The only thing I can think of is that the form needs to be redrawn or there is some threading issue that I’m unaware of.
Any insight you could provide would be greatly appreciated.
EDIT: Added some code to help
class Class1
{
public int number { get; set; }
public void Counter()
{
for (int i = 0; i < 10; i++)
{
number = i;
System.Threading.Thread.Sleep(5000);
}
}
}
and the form:
Class1 myClass = new Class1();
public Form1()
{
InitializeComponent();
label1.Text = myClass.number.ToString();
}
NO,
I think your form needs to access a reference to Class1 to use the data available in that, and not the other way around.
VERY seldomly a data class should instanciate a display form to display what it has to offer.
If the class is a data access layer of singleton, the form should reference that class, and not the other way around.
Based on the comments in your original post, here are a few ways to do it:
(this code is based on a Winform app in VS2010, there is 1 form, with a Label named "ValueLabel", a textbox named "NewValueTextBox", and a button.
Also, there is a class "MyClass" that represents the class with the changes that you want to publish.
Here is the code for the class. Note that I implement INotifyPropertyChanged and I have an event. You don't have to implement INotifyPropertyChanged, and I have an event that I raise whenever the property changes.
You should be able to run the form, type something into the textbox, click the button, and see the value of the label change.
public class MyClass: System.ComponentModel.INotifyPropertyChanged
{
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
public string AValue
{
get
{
return this._AValue;
}
set
{
if (value != this._AValue)
{
this._AValue = value;
this.OnPropertyChanged("AValue");
}
}
}
private string _AValue;
protected virtual void OnPropertyChanged(string propertyName)
{
if(this.PropertyChanged != null)
this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
Example 1: simple databinding between the label and the value:
So this time, we will just bind the label to an instance of your class. We have a textbox and button that you can use to change the value of the property in MyClass. When it changes, the databinding will cause the label to be update automatically:
NOTE: Make sure to hook up Form1_Load as the load event for hte form, and UpdateValueButton_Click as the click handler for the button, or nothing will work!
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private MyClass TheClass;
private void Form1_Load(object sender, EventArgs e)
{
this.TheClass = new MyClass();
this.ValueLabel.DataBindings.Add("Text", this.TheClass, "AValue");
}
private void UpdateValueButton_Click(object sender, EventArgs e)
{
// simulate a modification to the value of the class
this.TheClass.AValue = this.NewValueTextBox.Text;
}
}
Example 2
Now, lets bind the value of class directly to the textbox. We've commented out the code in the button click hander, and we have bound both the textbox and the label to the object value. Now if you just tab away from the textbox, you will see your changes...
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private MyClass TheClass;
private void Form1_Load(object sender, EventArgs e)
{
this.TheClass = new MyClass();
// bind the Text property on the label to the AValue property on the object instance.
this.ValueLabel.DataBindings.Add("Text", this.TheClass, "AValue");
// bind the textbox to the same value...
this.NewValueTextBox.DataBindings.Add("Text", this.TheClass, "AValue");
}
private void UpdateValueButton_Click(object sender, EventArgs e)
{
//// simulate a modification to the value of the class
//this.TheClass.AValue = this.NewValueTextBox.Text;
}
Example 3
In this example, we won't use databinding at all. Instead, we will hook the property change event on MyClass and update manually.
Note, in real life, you might have a more specific event than Property changed -- you might have an AValue changed that is only raised when that property changes.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private MyClass TheClass;
private void Form1_Load(object sender, EventArgs e)
{
this.TheClass = new MyClass();
this.TheClass.PropertyChanged += this.TheClass_PropertyChanged;
}
void TheClass_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "AValue")
this.ValueLabel.Text = this.TheClass.AValue;
}
private void UpdateValueButton_Click(object sender, EventArgs e)
{
// simulate a modification to the value of the class
this.TheClass.AValue = this.NewValueTextBox.Text;
}
}
There's no reason why you can't have multiple instances of a form, but in this case you want to pass the Class1 instance to the form you have. The easiest way is to add a property to Form1 and have that update the label text:
public class Form1 : Form
{
public Class1 Data
{
set
{
this.label.Text = value.LabelText;
}
}
}
Events and delegates are what you want to use here. Since you tagged this as beginner, I will leave the implementation as an exercise :), but here is the general idea:
Declare an event/delegate pair in your data class.
Create a method in your form to bind to the event.
When "something" happens in your data class, fire the event
The form's method will be invoked to handle the event and can update widgets appropriately
Good luck.

Categories