Following MVVM, I have an object persisted with the existence of a UI Window, object defined in XAML. This object represents the ModelView so it contains the controls which can modify the model. I am finding myself calling FrameworkElement.FindResource("myResource") for every user control. What is the proper way to grab the instance of this object?
XAML:
<p:MyModelView x:Key="modelView" />
CodeBehind:
//for every control I call:
public void SomeEventHandler(object _sender, EventArgs _someEventArgs) {
MyModelView repeatedCode= this.FindResource("modelView")
repeatedCode.DoSomeModificationRelatedToControl(args[] someArgs);
}
If you need your ViewModel a lot of places in your View code-behind, create and keep the ViewModel in a variable in the code-behind instead of creating it as a resource in your Xaml. For example:
public partial class MainWindow : Window
{
private MainViewModel _vm;
public MainWindow()
{
InitializeComponent();
_vm = new MainViewModel()
{
Name = "MyViewModel",
...
};
this.DataContext = _vm;
}
That last line is important - by making the ViewModel the View's DataContext, you can bind to it in Xaml like normal.
Now, your event handlers get at least a line or two shorter:
public void SomeEventHandler(object sender, EventArgs someEventArgs)
{
_vm.DoSomeModificationRelatedToControl(someArgs);
}
Related
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>
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)
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
I use a TabControl in one of my classes. However, I don't want to bloat this class and put all the code in it, as well as all the XAML for the TabItems.
After some Googling I've come up with the UserControl. So I created a UserControl for every TabItem, with the C# code of the TabItem in this UserControl.
The problem here, is that I need to transfer some data from my parent window (the one containing the TabControl) to the UserControls, to correctly display the data needed for that tab.
I created the UserControl in XAML and the code is like this:
<TabItem Name="userTab" Header="Gebruikers" HorizontalAlignment="Stretch">
<local:UserTabControl x:Name="userTabPanel"/>
</TabItem>
This is the constructor code for my UserControl:
public UserTabControl() {
setUsersView(); // NEED DATA FOR THIS
setUserData((User)usersView.SelectedItem);
InitializeComponent();
}
This is the class variable in the UserControl that needs a variable from the parent window: private static Parser m_config;
When I run this, I get a compile error saying :
"Object reference not set to an instance of an object."
pointing to the XAML line where I create my UserControl.
So, the conclusion here is I am yet unable to pass the variable to the UserControl and would like to have some suggestions or hints or guidance on how to do it in this case. Where am I going wrong here in achieving the required functionality ?
Im not sure that its the best way to do so, but for me it worked well.
For start I create CustomUserControl Class that inherit from UserControl with constractor that get his parent Form as an attribute like this:
public partial class CustomUserControl : UserControl
{
MainForm parentForm;
public CustomUserControl(MainForm mainForm)
{
parentForm = mainForm;
}
...
...
private void doSomthing()
{
parentForm.MainFormMember = 1;
}
}
And in the MainForm:
public partial class MainForm : Form
{
private int MainFormMember{ get; set; }
private CustomUserControl customUserControl;
public MainForm()
{
InitializeComponent();
// Create and add the CustomUserControl manually and not from ToolBox
customUserControl = new CustomUserControl(this);
this.Controls.Add(customUserControl);
}
...
...
}
In this way you can access the Form components from the UserControl
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.