ICommand Wpf form load properties?
-
I'm trying to update my program to WPF MVVM with Icommands to make my program look a little better and reduce the amount of event handlers, clutter etc, which I've managed to make workish. Well if I press a button in WPF my message box executes, so that's always good right? But I have some properties in my old windows form load event that I need to move over and I'm not exactly sure how I would implement that. I'm using the serialport io namespace and so I'm loading things like this at form load time:
SP.Handshake = Handshake.None;
SP.DataReceived += new SerialDataReceivedEventHandler(SP_DataReceived);SP meaning serial port. Do I put the above in my wpf form load event and make these public so that my modelview class can see them? Or is there an alternative? My model view class inherits from my viewbasemodel so it doesn't allow inheriting from another base class. I could move them to my viewbasemodel class, but I'm not sure about that one either. I still have to make them run at form load. I have to say I'm only half understanding the modelview at the moment. The tutorials online aren't clicking just yet. But I have made it workish so that's always good.
-
I'm trying to update my program to WPF MVVM with Icommands to make my program look a little better and reduce the amount of event handlers, clutter etc, which I've managed to make workish. Well if I press a button in WPF my message box executes, so that's always good right? But I have some properties in my old windows form load event that I need to move over and I'm not exactly sure how I would implement that. I'm using the serialport io namespace and so I'm loading things like this at form load time:
SP.Handshake = Handshake.None;
SP.DataReceived += new SerialDataReceivedEventHandler(SP_DataReceived);SP meaning serial port. Do I put the above in my wpf form load event and make these public so that my modelview class can see them? Or is there an alternative? My model view class inherits from my viewbasemodel so it doesn't allow inheriting from another base class. I could move them to my viewbasemodel class, but I'm not sure about that one either. I still have to make them run at form load. I have to say I'm only half understanding the modelview at the moment. The tutorials online aren't clicking just yet. But I have made it workish so that's always good.
geomeo123 wrote:
Do I put the above in my wpf form load event and make these public so that my modelview class can see them?
No. The ViewModel should not have any reference to the view. The quick fix would be to move the serial port comms into the ViewModel. A better option would probably be to move it to a separate "service" class consumed by the ViewModel, particularly if you want to introduce unit tests for your ViewModel classes.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
geomeo123 wrote:
Do I put the above in my wpf form load event and make these public so that my modelview class can see them?
No. The ViewModel should not have any reference to the view. The quick fix would be to move the serial port comms into the ViewModel. A better option would probably be to move it to a separate "service" class consumed by the ViewModel, particularly if you want to introduce unit tests for your ViewModel classes.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
Ok so I put them in ViewModel as a quick fix for now, but how would I call that from my xaml form? The xaml loaded event doesn't allow me to bind to my static resource(thinking I could just do another Icommand). Maybe because my static resource is called after I'm putting in loaded in xaml, but I can't think of any other way.
-
Ok so I put them in ViewModel as a quick fix for now, but how would I call that from my xaml form? The xaml loaded event doesn't allow me to bind to my static resource(thinking I could just do another Icommand). Maybe because my static resource is called after I'm putting in loaded in xaml, but I can't think of any other way.
The typical solution would be to use an "attached behaviour" to bind the
Loaded
event to your command. Introduction to Attached Behaviors in WPF[^] For example:public static class LoadedBehavior
{
public static readonly DependencyProperty LoadedCommandProperty = DependencyProperty.RegisterAttached(
"LoadedCommand",
typeof(ICommand),
typeof(LoadedBehavior),
new PropertyMetadata(null, OnLoadedCommandChanged));public static ICommand GetLoadedCommand(FrameworkElement obj) { return (ICommand)obj.GetValue(LoadedCommandProperty); } public static void SetLoadedCommand(FrameworkElement obj, ICommand value) { obj.SetValue(LoadedCommandProperty, value); } private static void OnLoadedCommandChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { FrameworkElement element = obj as FrameworkElement; if (element == null) return; if (e.OldValue == null) { element.Loaded += OnLoaded; } else if (e.NewValue == null) { element.Loaded -= OnLoaded; } } public static readonly DependencyProperty LoadedCommandParameterProperty = DependencyProperty.RegisterAttached( "LoadedCommandParameter", typeof(object), typeof(LoadedBehavior), new PropertyMetadata(null)); public static object GetLoadedCommandParameter(FrameworkElement obj) { return obj.GetValue(LoadedCommandParameterProperty); } public static void SetLoadedCommandParameter(FrameworkElement obj, object value) { obj.SetValue(LoadedCommandParameterProperty, value); } private static void OnLoaded(object sender, RoutedEventArgs e) { FrameworkElement element = sender as FrameworkElement; if (element == null) return; ICommand command = GetLoadedCommand(element); if (command == null) return; object parameter = GetLoadedCommandParameter(element); command.Execute(parameter); }
}
-
Ok so I put them in ViewModel as a quick fix for now, but how would I call that from my xaml form? The xaml loaded event doesn't allow me to bind to my static resource(thinking I could just do another Icommand). Maybe because my static resource is called after I'm putting in loaded in xaml, but I can't think of any other way.
Another option would be to use Microsoft's XamlBehaviorsWpf library: GitHub - microsoft/XamlBehaviorsWpf: Home for WPF XAML Behaviors on GitHub.[^] That provides an InvokeCommandAction[^] which lets you invoke an
ICommand
in response to an event.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
Another option would be to use Microsoft's XamlBehaviorsWpf library: GitHub - microsoft/XamlBehaviorsWpf: Home for WPF XAML Behaviors on GitHub.[^] That provides an InvokeCommandAction[^] which lets you invoke an
ICommand
in response to an event.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer