The problem occour when I try to assign (subscribe) a ToggleButton
to a event handler in a different file (for example: XAML is named PrimaryPage.xaml
and a C# file is named different like EventHandler.cs
, not PrimaryPage.xaml
) in the same solution as I wanted to seperate things up.
Here's what I meant:
ToggleButton
in XAML:<ToggleButton
x:Name="PumpBTN"
IsThreeState="False"
Checked="PumpBTN_C"
Unchecked="PumpBTN_U"
Content="Pump" />
PrimaryPage.xaml.cs
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml;
using WinUI.XXXX.EventHandler; // Include EventHandler
namespace WinUI.XXXX.Views;
public partial class PrimaryPage : Page // Unsealed
{
public PrimaryViewModel ViewModel
{
get;
}
public PrimaryPage()
{
ViewModel = App.GetService<PrimaryViewModel>();
InitializeComponent();
Event event = new Event();
PumpBTN.Checked += event.PumpBTN_C; // Pump-checked subscription
PumpBTN.Unchecked += event.PumpBTN_U; // Pump-unchecked subscription
}
}
EventHandler.cs
:using System.IO.Ports;
using WinUI.XXXX.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml;
namespace WinUI.XXXX.EventHandler;
public partial class Event
{
public readonly SerialPort serial_port = new();
public Serial()
{
Main();
}
public string Main()
{
// Serial port stuffs
return 'strings' // Just for an example
}
public void PumpBTN_C(object sender, RoutedEventArgs e) // Event handler
{
// Code
}
public void PumpBTN_U(object sender, RoutedEventArgs e) // Event handler
{
// Code
}
I think I alredy do everything that I needed to, I aleady type using
followed by the corresponding namespaces, I already subscribe and create a event handler as needed.
I'm just started developing GUI with C# and XAML in WinUI3 a few weeks ago, and I've no experience in writing in OOP languages before, So I have no idea what should I do next. Any ideas?
The typical way is to use MVVM to bind the IsChecked property of the View to a property in the ViewModel:
view
<CheckBox IsChecked="{Binding MyIsCheckedProperty}">
Pump
</CheckBox>
ViewModel
public class MyViewModel : INotifyPropertyChanged
{
private bool myIsCheckedValue;
public bool MyIsCheckedProperty
{
get => myIsCheckedValue;
set
{
if (value != myIsCheckedValue)
{
myIsCheckedValue = value;
OnPropertyChanged();
// Do other stuff
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
You can add an event to your MyViewModel
, and raise it at the // Do other stuff
point to inform other components. Or just make a call to some method to inform it that the checkbox has changed. The idea with the pattern is that the "ViewModel" classes should interact with and update a "Model" that represents the overall state of your application.
Note that you will need to ensure the DataContext object of your view is set to the viewModel object. For example by using a little bit of code behind:
public partial class MyMainWindow : Window
{
private MainWindowViewModel mwmv;
public MyMainWindow ()
{
InitializeComponent();
DataContext = new MyViewModel;
}
}
This is typically only done for the root window, and use bindings to associate any other views with viewModels. This needs to be done since all bindings are relative to the DataContextObject.