WPF passing data from Window to a running User Control [closed] - c#

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm new in WPF world. I have a UserControl and a Button inside it. When button clicked, a selector Window open in new Window and running with UserControl at same time.
I want in second window when user select a value, pass this value back to UserControl then close window. How can I do this? is DataBinding with INotifyPropertyChangedclass the best way? How can I implement this?
solution:
From Microsoft document and delegate and EventHandler meanings, I do the following. I have a UserControl with name BuyFactor. When user click Add Item new Window with name AddItem raised. When new item selected and when Add This clicked, I want to send Item Id back to BuyFactor with EventHandler:
BuyFactor UserControl:
public partial class BuyFactor: UserControl
{
Dialogs.AddItem publisher;
public TaqehBuyFactor()
{
InitializeComponent();
publisher = new Dialogs.AddItem();
publisher.RaiseCustomEvent += HandleCustomEvent;
}
void HandleCustomEvent(object sender, Dialogs.CustomEventArgs e)
{
//Should change text when button clicked on Window (publisher)
ProductName.Text = e.Message;
}...}
AddItem Window:
public partial class SelectTaqehDialog : Window
{
public event EventHandler<CustomEventArgs> RaiseCustomEvent;
public void DoSomething()
{
// Write some code that does something useful here
// then raise the event. You can also raise an event
// before you execute a block of code.
OnRaiseCustomEvent(new CustomEventArgs("Did something"));
}
protected virtual void OnRaiseCustomEvent(CustomEventArgs e)
{
// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler<CustomEventArgs> handler = RaiseCustomEvent;
// Event will be null if there are no subscribers
if (handler != null)
{
// Format the string to send inside the CustomEventArgs parameter
e.Message += String.Format(" at {0}", DateTime.Now.ToString());
// Use the () operator to raise the event.
handler(this, e);
}
}
private void addToFactor_Click(object sender, RoutedEventArgs e)
{
// Fire when Add This button clicked
DoSomething();
}
And My CustomEventArgs:
public class CustomEventArgs : EventArgs
{
public CustomEventArgs(string s)
{
message = s;
}
private string message;
public string Message
{
get { return message; }
set { message = value; }
}
}
Pay attention that call publisher.Show() for creating new window.

// in MainWindow or somewhere
myUserControl.someBtn.Click += (se, a) => {
var mw = new MyWindow();
mw.Show();
mw.myEvent += (myEventSender, myComboBoxFomMyWindow) => MessageBox.Show(myComboBoxFromMyWindow.SelectedItem as string);
};
// MyWindow
public event EventHandler<ComboBox> MyEvent;
public MyWindow() {
myComboBox.SelectionChanged += (se, a) => MyEvent?.Invoke(this, myComboBox);
}
Hope it works!

Related

Is there a way to activate a Button that exists within another class?

I am using C# and Xamarin. I have two separate classes. One class is essentially the user interface and another class is acting as a custom built generic entry for users to input data and search for results by clicking a button.
Main UI Class:
Class MainPage
{
public MainPage
{
Content = new StackLayout
{
Children =
{
new InputClass // This is my custom built user entry class
{
}.Invoke(ic => ic.Clicked += WhenButtonPressedMethod) // The problem is here, I can't figure out how to call the button within the input class to fire a clicked event.
}
}
}
}
public async void WhenButtonPressedMethod (object sender, EventArgs e)
{
// Supposed to do stuff when the button is pressed
}
InputClass:
public class InputClass : Grid
{
public delegate void OnClickedHandler(object sender, EventArgs e);
public event OnClickHandler Clicked;
public InputClass
{
Children.Add(
new Button {}
.Invoke(button => button.Clicked += Button_Clicked)
)
}
private void Button_Clicked(object sender, EventArgs e)
{
Clicked?.Invoke(this, e);
}
}
The "InputClass" is a grid that holds a title text label, an entry and a button that a user can press to submit and search data. The button in this class is what I'm trying to actually access to invoke/cause a click event so that the method in the main UI class can be called. But, when I try to invoke a click event on the "InputClass" I can't access the button inside of it, I can only access "InputClass" itself which is just a grid with no useful event properties.
Any solutions or ideas?
If you are running into the same problem as mentioned here, follow the code on this page and read through the comments, it covers enough to be able to piece it together. My mistake was attaching Invokes to the wrong objects.
Don't know why fluent Invoke didn't work correctly.
Add the event handlers this way:
public MainPage
{
var ic = new InputClass();
ic.Clicked += WhenButtonPressedMethod;
Content = new StackLayout
{
Children = { ic }
}
}
public InputClass
{
var button = new Button;
button.Clicked += Button_Clicked;
Children.Add(button);
}

Calling method from a frame when a button is triggered in other frame

I would like to call a method from another frame when pressing a button in another frame, the only code I currently have is this + the button in my AddReview.cs (Windows Form Frame)
Method that should be called: (This is located in MainScreen.cs)
public void GetTrackLayout()
{
TrackInformation t = new TrackInformation(lblMainScreen_Username.Text, cBMainScreen_Search.SelectedValue.ToString());
fPanelUpperMainScreen.Controls.Add(t);
int valueInt = int.Parse(cBMainScreen_Search.SelectedValue.ToString());
t.pbTrackInformation_image.ImageLocation = tr.GetTrack(valueInt).trackPicture;
t.lblTrackInformation_Title.Text = tr.GetTrack(valueInt).title;
t.lblTrackInformation_RevType.Text = "Track".ToUpper();
var reviews = rr.GetMatchingReviewsTrack(valueInt);
t.lblTrackInformation_Count.Text = reviews.Count().ToString();
foreach (var review in reviews)
{
UserControl1 u = new UserControl1();
u.lblUser.Text = review.username;
u.lblComment.Text = review.comments;
u.lblDate.Text = review.date;
u.lblRating.Text = review.rating.ToString();
t.fpTrackInformation_Reviews.Controls.Add(u);
}
}
On my MainScreen.cs I've added a User Control which is called TrackInformation.cs (not much code to show here, hence why I am not posting it) and in this layout the button that Add the review is available.
You can create an event in your AddReview form:
partial class AddReview : Form
{
public event EventHandler SpecialButtonClicked;
public AddReview()
{
InitializeComponent();
// Normally you'd hook this up in the Designer, but for the sake of
// illustration, I show the subscription here
button1.Click += button1_Click;
}
private void button1_Click(object sender, EventArgs e)
{
EventHandler handler = SpecialButtonClicked;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
partial class MainScreen : Form
{
private void SomeMethod()
{
AddReview addReview = new AddReview();
addReview.SpecialButtonClicked += (sender, e) => GetTrackLayout();
addReview.Show();
}
}
In other words, the AddReview form exposes an event that the MainScreen form can subscribe to. When the button is clicked, the AddReview form raises the event. When you create the AddReview form, you subscribe to it and call your method in the handler.

How to add events in C#? [duplicate]

This question already has answers here:
How to add an event to a UserControl in C#?
(6 answers)
Closed 8 years ago.
I am learning event handling in C# and have just learnt the basic usage of
delegates
I was looking for a way to add some events to my GUI App. for ex, check the following code:-
private void label1_Click(object sender, EventArgs e)
{
MessageBox.Show("Hello World") ;
}
This function displays the MessageBox with the content HelloWorld whenever I click on the label label1. I wanted to know , how can we add various other events like hovering over the label and other such events. Also, what is the use of the parameter
sender and e
label1.OnMouseHover += myDelegate will add your delegate to the mouseover event.
See list of events.
label1.Click += new System.EventHandler(label1_Click);
You'll get it better if you create a class and add your own event to it.
The default "e" is a an instance of System.EventArgs
You can derived from that to have your own
e.g.
public class MyEventArgs : System.EventArgs
{
public string EventData {get; private set;}
public MyEventArgs(String argEventData)
{
EventData = argEventData;
}
}
Then to use the above in a class
public class SomeFellaWithAnEvent
{
public event EventHandler<MyEventArgs> OnMyEvent;
private int _value;
public int Value
{
get {return _value;}
set
{
if (_value != value)
{
_value = value;
DoEvent(_value.ToString();
}
}
}
protected void DoEvent(String argData)
{
if (OnMyEvent != null)
{
OnMyEvent(this,new MyEventArgs(argData))
}
}
}
So now you have something where if Value get's changed it will raise an event if you've given it a handler
e.g
SomeFellaWithAnEvent o = new SomeFellaWithAnEvent()
o.OnMyEvent += someThingChanged();
o.Value = 22;
private void somethingChanged(Object sender, MyEventArgs e)
{
// do something with it.
// debug this and you'll see sender is the o instance above, and e is the instance
// of MyEventArgs created in the DoEvent method and has a property set to "22"
}
To add more event handlers to existing controls from the tool box. Click the events tab (lightning button) in the property inspector and then double click in the value.
Or in the code view type label1.Click +=
and then press tab twice.

using delegate to send string

I'am having a very annoying problem in my code, when I try to send a string from Form B to form a. I get the error message:
Object reference not set to an instance of an object.
I'am familiar with this error and normally I know how to solve this problem, but this one is different.
I need to send a Clockname from one form to the main form, I'am trying to achieve this using the code below:
delegate void ClockClocknameReceivedEventHandler(object sender, Clock.ClocknameReceivedEventArgs e);
internal class ClocknameReceivedEventArgs : EventArgs
{
string _clockname;
public string Clockname
{
get { return _clockname; }
}
public ClocknameReceivedEventArgs(string clockname)
{
_clockname = clockname;
}
}
// An event that clients can use to be notified whenever the
// elements of the list change.
public event ClockClocknameReceivedEventHandler ClocknameReceived;
// Invoke the Changed event; called whenever list changes
protected void OnClocknameReceived(Clock.ClocknameReceivedEventArgs e)
{
ClocknameReceived(this, e);
}
And the following code gets fired when pressing a button, the form will close after that:
OnClocknameReceived(new Clock.ClocknameReceivedEventArgs(ClockName));
The error(Object reference not set to an instance of an object.) I receive occurs at
ClocknameReceived(this, e);
I'am using the exact same code, from another class to the main form to send a byte array which works fine, but this one give me that error.
Anyone any ideas?
Thanks in advance!
The delegate can be null. Invoke it only if it's not null:
protected void OnClocknameReceived(Clock.ClocknameReceivedEventArgs e)
{
ClockClocknameReceivedEventHandler handler = ClocknameReceived;
if (handler != null)
{
handler(this, e);
}
}
The delegate is null when you haven't subscribed an event handler to the event yet. Subscribe an event handler:
formB.ClocknameReceived += FormB_ClocknameReceived;
with
void FormB_ClocknameReceived(object sender, Clock.ClocknameReceivedEventArgs e)
{
MessageBox.Show(e.Clockname);
}
Your not checking whether the ClocknameReceived event has been assigned (i.e. has any subscribers). Typical event handling code generally looks like:
var handler = ClocknameReceived;
if (handler != null)
{
handler(this, e);
}
This type of approach also mitigates (to an extent) race conditions with your event handler as it could be unassigned by the time you go to trigger it.
Looking at your code you could definitely tidy this up a bit. For one, your EventArgs class could be re-written with less code:
internal class ClocknameEventArgs : EventArgs
{
public ClockNameEventArgs(string name)
{
Name = name;
}
public string Name { get; private set; }
}
Then in your form, there's no need for a delegate if you have a particular type of EventArgs, your event can be declared as:
public event EventHandler<Clock.ClocknameEventArgs> ClocknameReceived;
You then hook up to this event somewhere (maybe in the FormCreate event?):
ClocknameReceived += (sender, args) {
FormB.PassName(args.Name);
};
You have to check if the event has a delegate or not
if( ClocknameReceived != null)
ClocknameReceived(this, e);

How can a UserControl trigger an selectionChanged event to a Window?

I want to make a ColorPicker userControl, and put inside a window.
When the user click in any rectangle of the usercontrol, then I want to return this information to the Window. How can I do this please? Thanks!
Your Color Picker UserControl has to implement an event that is raised every time the user clicks on one of the rectangles of the UserControl. If you don't know how to implement an event, just comment this answer and I give you an example.
Here is the example: You declare your own event args (if needed) to provide some information in the event:
class RectangleClickedEventArgs : EventArgs
{
public int SomeValue { get; set; }
}
In your usercontrol you declare the event:
public event EventHandler<RectangleClickedEventArgs> RectangleClicked;
In some condition you raise the event in this way (the thread-safe way:
var temp = RectangleClicked;
if (temp != null)
{
var e = new RectangleClickedEventArgs{ SomeValue = 42};
temp(this, e);
}
In your form you subscribe the event:
userControl.RectangleClicked += OnRectangleClicked;
And in the event routine you do your desired action:
private void OnRectangleClicked(object sender, RectangleClickedEventArgs e)
{
// Do what you want to do
}
Hope that helps...

Categories