I am working on a WPF project, and I implemented the MVC -Pattern for my application . So I have the MainWindow.xaml and MainWindow.xaml.cs as the View, and then a Controller and a Model class (first time that I did this). Everything works great so far. But here is what i don't like: When I have an event defined in the xaml file, lets take:
<Button Content="Save" Click="SaveButton_ClickEvent"/>
then whenever the Save Button is clicked, the function in the xaml.cs file is called:
private void SaveButton_ClickEvent(object sender, RoutedEventArgs e)
{
Controller.Save();
}
I actually have a lot of those functions in the xaml.cs file, where there is a function that just calls another fuction in the controller, and it seems kind of wasteful to me. Isn't there a better way of doing this? I think I have read somewhere that if one implements the MVC-pattern in WPF, the xaml.cs file stays almost empty. So my question is:
Is there a way to call a Method in my controller (or any other) class from within the .xaml file wihtout putting a function in the xaml.cs file? (and if yes, how would i do that)
Or did I get it all wrong and this is all done differently?
If you don't want to implement the recommended MVVM design pattern and replace the event handler with a binding that binds the Command
property of the Button
to an ICommand
property of a view model, you could for example implement an attached behaviour that handles the Click
event and calls your controller:
public static class Mvc
{
public static readonly DependencyProperty ClickProperty =
DependencyProperty.RegisterAttached(
"Click", typeof(string), typeof(Mvc),
new PropertyMetadata(string.Empty, OnChanged));
public static string GetClick(Button obj) =>
(string)obj.GetValue(ClickProperty);
public static void SetClick(Button obj, string value) =>
obj.SetValue(ClickProperty, value);
private static void OnChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (!string.IsNullOrEmpty(e.NewValue as string)
&& obj is Button button)
{
button.Click += OnButtonClick;
}
}
private static void OnButtonClick(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
object controller = button.DataContext;
if (controller != null)
{
string methodName = GetClick(button);
if (!string.IsNullOrEmpty(methodName))
{
controller.GetType()
.GetMethod(methodName)?
.Invoke(controller, null);
}
}
}
}
XAML:
<Button Content="Save" local:Mvc.Click="Save"/>
Code-behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new Controller();
}
}
Controller:
public class Controller
{
public void Save()
{
//save...
}
}