UserControls using the same events - c#

I'm making Windows 10 UWP app.
To make it simple, let's say I have a TextBox somewhere on my page. Under this TextBox there are my 3 (different types) custom controls. These 3 controls have the same property and event that is raised if user clicks a button inside one of these controls, and the method to which this event is subscribed to causes that the text inside a TextBox is assigned to SomeProperty in the control.
Is there some way to subscribe to these events, so that I don't have to have 3 different methods handling it while they're literally doing the same thing, but for 3 different controls.
This is the code that all of the controls have in common. There are MyControlA, MyControlB and MyControlC
public sealed partial class MyControlA : UserControl
{
public delegate void StartPositionClickedEventHandler(object sender, EventArgs e);
public event StartPositionClickedEventHandler StartPositionClicked;
public string SomeProperty
{
get { return (string)GetValue(SomePropertyProperty); }
set { SetValue(SomePropertyProperty, value); }
}
private void StartPosition_Click(object sender, RoutedEventArgs e)
{
StartPositionClicked?.Invoke(this, EventArgs.Empty);
}
// Using a DependencyProperty as the backing store for SomeProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SomePropertyProperty =
DependencyProperty.Register("SomeProperty", typeof(string), typeof(MyControlA), null);
}
I subscribe to the event in the page where the control is
_control.StartPositionClicked += new MyControlA.StartPositionClickedEventHandler(SetCurrentStartPositon);
and handle it
private void SetCurrentStartPositon(object sender, EventArgs e)
{
_control.SomeProperty = DummyTextBox.Text;
}
And I would have to do that for all of the controls, but I might have lots of them as they're created programmatically as they're needed, so I wish to have some better way of doing it. Everything I thought of seems to be dumb or super inefficient.
Thank you in advance!

Since all your controls have the same properties of the same type, there are two ways how to achieve what you want:
1: Creating a base class that will implement the code they all have in common and make all the controls inherit from it:
public abstract class MyControlBase : UserControl
{
public delegate void StartPositionClickedEventHandler(object sender, EventArgs e);
public event StartPositionClickedEventHandler StartPositionClicked;
public string SomeProperty
{
get { return (string)GetValue(SomePropertyProperty); }
set { SetValue(SomePropertyProperty, value); }
}
protected void StartPosition_Click(object sender, RoutedEventArgs e)
{
StartPositionClicked?.Invoke(this, EventArgs.Empty);
}
// Using a DependencyProperty as the backing store for SomeProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SomePropertyProperty =
DependencyProperty.Register("SomeProperty", typeof(string), typeof(MyControlA), null);
}
public sealed partial class MyControlA : MyControlBase
{
// Class specific code
}
Please note that you'll also need to change the base class in XAML so instead of something like
<UserControl>
<!-- Your XAML code -->
</UserControl>
you have to use something like this assuming xmlns:local points to the namespace in which MyControlBase is:
<local:MyControlBase>
<!-- Your XAML code -->
</local:MyControlBase>
Then you can make one event handler that will look similar to this:
private void SetCurrentStartPositon(object sender, EventArgs e)
{
// Get the control that invoked this event
MyControlBase senderControl = (MyControlBase)sender;
senderControl.SomeProperty = DummyTextBox.Text;
}
2: Creating a simple interface for them like this and make all the three controls inherit from it:
public interface IMyControl
{
string SomeProperty { get; set; }
}
So in your code, you could subscribe events of all the controls to one method that will look like this one:
private void SetCurrentStartPositon(object sender, EventArgs e)
{
// Get the control that invoked this event
IMyControl senderControl = (IMyControl)sender;
senderControl.SomeProperty = DummyTextBox.Text;
}
I'd suggest using the first option since it makes your code simplier to read and avoids possible inconsistencies from changing the common code.

Yes you can!
It is called EventSetter and you can use it like this:
<Style TargetType="{x:Type local:MyControlA}">
<EventSetter Event="StartPositionClicked" Handler="SomeAction"/>
</Style>
You need to put this style in the parent control i.e. Grid or StackPanel and also you need to implement the SomeAction method.
HTH

Related

How to separate event code behind to seperate class?

So far i separated action with Command Binding. but i need to implent many thing to work same as built-in event. ex, OnClick, OnChange and so on. the MVVM pattern only means is no code behind in ViewModel class. all thing like Component. instead make all thing from scratch. why not just make Event in ViewModel implementation like component. so just attacch and detach that event collection class. is there new way to do this? so far i can think is encapsulate control with event and inhrited to viewmodel class.
public class Utility
{
public static string Manipulation(string search)
{
return search + "Reesult";
}
}
public class CustomWindow : Window
{
protected virtual void SearchBtn(object sender, RoutedEventArgs e)
{
MessageBox.Show( Utility.Manipulation(search.Text) );
}
}
public partial WindowViewModel : CustomWindow
{
public WindowViewModel
{
InitializeComponent();
}
}
<TextBox x:Name="search" />
<Button Click="SearchBtn"> Search </Button>

Define custom path for control events

I've been working a lot with WPF, and after awhile the MainWindow class becomes cluttered and unorganized. Is there a way to store all of the control events in a custom class like below? Inheriting doesn't work and i'm guessing its because it has no instance of the new class to go off of.
public partial class MainWindow : Window
{
public class ControlEvents : MainWindow //Custom class
{
private void Abutton_Click(object sender, RoutedEventArgs e)
{
...Stuff
}
}
}
Is there a way to store all of the control events in a custom class like below?
No, the event handlers themselves must be defined in the code-behind of the same view class where the element is defined and the handler is hooked up.
You could move the code inside the event handlers to another class though:
public partial class MainWindow : Window
{
private YourClass _handler = new YourObject();
public class ControlEvents : MainWindow //Custom class
{
private void Abutton_Click(object sender, RoutedEventArgs e)
{
_handler.HandleButtonClick(e);
}
}
}
But you should look into MVVM: https://msdn.microsoft.com/en-us/library/hh848246.aspx. There is a reason why this is the recommended design pattern for developing XAML based UI applications.
If you don't use mvvm:
You can create user control for area of controls and load this user control in your main window.
Also - you can take your code of "do stuff" to another class and call it from the event function.
for example:
functions.cs
dostuff1()
{
...
}
dostuff2()
{
...
}
your usercontrol/mainwindow.xaml.cs:
functions f = new functions();
private void Abutton_Click(object sender, RoutedEventArgs e)
{
f.dostuff1();
}
good luck
You can move all the events to Partial class in separated file.
call the file MainWindowEvents.cs or something. (to remember what is it)

How to move methods to external file in windows form C#

newbie question :(
I'm making a program using windows forms and i have a lot of small methods like this
private void label1_Click(object sender, EventArgs e)
{
textBox1.Select();
}
private void label13_Click(object sender, EventArgs e)
{
textBox13.Select();
}
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
plotGraph(prostokat);
}
in the Form1.cs file and to make the code more transparent, I would like to move these small methods out somewhere to an external file (class?) but I don't really know how to do this. If they were normal methods I would just make a class and create an object of that class and just call the methods using that object but these are functions that "happen" when a user action is performed i.e. a textbox is clicked, so I'm not sure how to make this work.
It is possible to create an extra partial class (separated file) for your Form1 and place your cluttering methods there.
Or you could collapse them with #region
#region UI Handlers
#endregion
The perfect solution would be using some kind of MVVM for WinForms. In that case in your ViewModel you can implement your business logic separately from the code-behind.
Check out this:
https://www.codeproject.com/articles/364485/mvvm-model-view-viewmodel-patte
Hope it helps!
Have a look at your Form class subsection. It most cases it is still a partial class. Create a new .cs file in the same subsection in your project and add another partial form class to it.
You can find additional information here:
Partial Classes and Methods
Sure, you can add a new class to your project (right-click the project in Solution Explorer --> Add Class --> ) and put your methods there. Then you will need to hook the methods up to the controls in code:
I added a static class called "Form Methods" and put a method in there for label1 Click event:
static class FormMethods
{
public static void label1_Click(object sender, EventArgs e)
{
Label label = (Label) sender;
// Try to find the textbox through the label's parent form
TextBox textBox = (TextBox) label.Parent.Controls.Find("textBox1", true).First();
if (textBox != null)
{
textBox.Select();
}
}
}
Then in the Form Designer code, you can hook up the event:
this.label1.Click += new System.EventHandler(FormMethods.label1_Click);
Alternatively, you can make the class part of your original form class, and it will still be a separate file. If you want to do this, you can then make your event a private non-static method, and you would change the class definition to a public partial class:
public partial class Form1 // <-- This used to be: static class FormMethods
{
// This used to be: public static void label1_Click
private void label1_Click(object sender, EventArgs e)
{
. . .
And then hooking up the event looks like:
this.label1.Click += new System.EventHandler(label1_Click);
You can create any number of partial class files mimicking your original and group methods inside as your functionally needs - however, you won't be able to use the designer to directly navigate to your callbacks. That is, if you double click a graphic element or click an event of a graphic element you will have an unexpected behavior: in both cases you will have an event handler generated in your first partial and a hook created to that . . . so you can't directly navigate to those handlers anymore, and you need to go trough your partial files looking for their definitions.
Use partial to split C# code like this.
public partial class Employee
{
public void DoWork()
{
}
}
public partial class Employee
{
public void GoToLunch()
{
}
}

How to get the value from a listBox1_SelectedIndexChanged event from another class?

I have a main form with a listbox, I also have a listBox1_SelectedIndexChanged event and more code going on for each item when it changes.
Is there a simple way to make this event in another class and not on the main form?
If not, as I meant, I don't want all this code on my main form's code so I want to move it to another class where it is more related.
what is the "best practice" way to notify Class B when listBox1_SelectedIndexChanged occurs? is it by a delegate? I tried to figure it out but didn't really understand. Help will be much appreciated.
Thanks.
I am not sure how both classes are linked to each other and their types but using following code you can get idea to solve your problem
public class A
{
public delegate void ItemSelectedHandler(string title);
public event ItemSelectedHandler OnItemSelected;
public void listBox1_SelectedIndexChanged(object sender, EventArg, e)
{
//other code
if(OnItemSelected!=null)
{
OnItemSelected("Something");
}
}
public void LaunchB()
{
var b = new B(this);
b.ShowDialog();
}
}
public class B
{
private A _parent;
public B(A parent)
{
_parent = parent;
_parent.OnItemSelected += onItemSelected;
}
public void onItemSelected(string title)
{
//will fire when selected index changed;
}
}
I think I solved my question in a simpler way.
I set the listbox1 access modifier to Internal
I created properties for the main form.
In Class B, I subscribed to the listBox1.SelectedIndexChanged event and created an event handler like this:
form1Properties.listBox1.SelectedIndexChanged+=listBox1_SelectedIndexChangedforClassB;
Then I've implemented the event handler in Class B like this:
private void listBox1_SelectedIndexChangedforClassB(object sender, EventArgs e)
{
MessageBox.Show("listbox1 selected item has changed!");
}
I hope I am using all the right terms, please correct me if I'm wrong, and please tell me if you find my solution is flawed in any way. Thanks.

User Control to pass event back to parent form

I have a main form with 3 User Controls attached to it. How can I have events inside a specific User Control reach out and modify the UI of the other two User Controls without creating spaghetti code?
Main Form (Form1.cs)
public partial class Form1 : Form
{
private UserControl1 userControl11;
private UserControl2 userControl21;
private UserControl3 userControl31;
public Form1()
{
InitializeComponent();
}
}
UserControl1.cs
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Change buttons around and fill in some data on user control 2 and 3
}
private void button2_Click(object sender, EventArgs e)
{
// Remove certain elements from control2 and 3
}
// .. So forth
}
I will have many events that do many different things on the other two user controls. I am creating a basic interface that's similar to Visual Studio where I can open projects, close them, add files, etc. These actions on one form should load up different windows and such in the other controls. What's the best method to achieve this? Creating custom events and parsing each event in the main form? Or accessing each user control directly from the first one? Or...?
The general pattern for events is:
public class MyClass{
public static EventHanlder<ofSomeType> MyEventHandler;
public void MyClass{
MyEventHandler = _MyEventHandler;
}
public void _MyEventHandler(object sender, OfSomeType args){
//do something with passed in args.
}
}
Other classes would use these eventhandlers like this...
public class myOtherClass{
public void doSomething(){
//do something here and signal the other class
var ofSomeTypeData = GetData();
MyClass.MyEventHandler(ofSomeTypeData);
}
}
Some will argue this style is too closely coupled but it works flawlessly and is a good start.
Create an event inside each UserControl. Form1 should subscribe to events on those controls.
So suppose that UserControl1 allows the user to sort the data. Then you might write this:
public Form1()
{
InitializeComponent();
// I assume UserControl1 was created by this point
userControl1.OnDataSorted = DataSorted;
}
// This will be called when the user wants to sort the data
private void DataSorted(UserControl1 sender, EventArgs e)
{
// Change buttons around and fill in some data on user control 2 and 3
}
Then you will create an event and a delegate in the UserControl.
public class UserControl1 {
public delegate void DataSortedDelegate(UserControl1 sender, EventArgs e);
public event DataSorted OnDataSorted;
private void button1_Click(object sender, EventArgs e)
{
if (OnDataSorted != null)
OnDataSorted(this, EventArgs.Empty);
// Replace EventArgs.Empty above with whatever data Form1 needs
}
This approach creates a separation of concerns between Usercontrol1 and Form1. The control does not need to actually modify the private controls inside Form1. It merely notifies Form1 that something has happened, and allows Form1 to make the changes.

Categories

Resources