I have a simple menu and would like the IsChecked property of the MenuItems to be bound so that I could later manipulate them in code behind. I have a break point set in the getter and setter of the property but they are never hit.
I've searched other questions and none have shed any light on my issue. I created a skeleton project to demonstrate what I'm seeing.
MainWindow.xaml:
<Window x:Class="POC_BindingMenuItemIsChecked.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:POC_BindingMenuItemIsChecked"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:MainWindowViewModel x:Key="mainWindowViewModel"/>
</Window.Resources>
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="Choice">
<MenuItem Header="Alpha"
IsCheckable="True"
Checked="MenuItemAlpha_Checked"
IsChecked="{Binding AlphaIsRecording, Mode=TwoWay}"/>
<MenuItem Header="Bravo"
IsCheckable="True"
Checked="MenuItemBravo_Checked"
IsChecked="{Binding
Source={StaticResource mainWindowViewModel},
Path=BravoIsRecording,
Mode=TwoWay}"/>
<MenuItem Header="Charlie"
IsCheckable="True"
Checked="MenuItemCharlie_Checked"
IsChecked="{Binding CharlieIsRecording, Mode=TwoWay}"/>
</MenuItem>
</Menu>
</DockPanel>
</Window>
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
private MainWindowViewModel _MainWindowViewModel = null;
public MainWindow()
{
InitializeComponent();
// get a reference to the binding sources so we can set the properties
_MainWindowViewModel = new MainWindowViewModel();
this.DataContext = _MainWindowViewModel;
}
private void MenuItemAlpha_Checked(object sender, RoutedEventArgs e)
{
//no-op yet
}
private void MenuItemBravo_Checked(object sender, RoutedEventArgs e)
{
//no-op yet
}
private void MenuItemCharlie_Checked(object sender, RoutedEventArgs e)
{
//no-op yet
}
}
MainWindowViewModel.cs:
class MainWindowViewModel : DependencyObject
{
// Alpha
public static PropertyMetadata AlphaIsRecordingPropertyMetadata
= new PropertyMetadata(null);
public static DependencyProperty AlphaIsRecordingProperty
= DependencyProperty.Register(
"AlphaIsRecording",
typeof(bool),
typeof(MainWindowViewModel),
AlphaIsRecordingPropertyMetadata);
public bool AlphaIsRecording
{
get { return (bool)GetValue(AlphaIsRecordingProperty); }
set { SetValue(AlphaIsRecordingProperty, value); }
}
// Bravo
public static PropertyMetadata BravoIsRecordingPropertyMetadata
= new PropertyMetadata(null);
public static DependencyProperty BravoIsRecordingProperty
= DependencyProperty.Register(
"BravoIsRecording",
typeof(bool),
typeof(MainWindowViewModel),
BravoIsRecordingPropertyMetadata);
public bool BravoIsRecording
{
get { return (bool)GetValue(BravoIsRecordingProperty); }
set { SetValue(BravoIsRecordingProperty, value); }
}
// Charlie
public static PropertyMetadata CharlieIsRecordingPropertyMetadata
= new PropertyMetadata(null);
public static DependencyProperty CharlieIsRecordingProperty
= DependencyProperty.Register(
"CharlieIsRecording",
typeof(bool),
typeof(MainWindowViewModel),
CharlieIsRecordingPropertyMetadata);
public bool CharlieIsRecording
{
get { return (bool)GetValue(CharlieIsRecordingProperty); }
set { SetValue(CharlieIsRecordingProperty, value); }
}
}
EDIT:
Because of the solution that mm8 provided (POCO and not Dependency) I've modified the solution. It now functions as a set of three MenuItems that behave as radio buttons. The code follows:
MainWindow.xaml:
<Window x:Class="POC_BindingMenuItemIsChecked.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:POC_BindingMenuItemIsChecked"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:MainWindowViewModel x:Key="mainWindowViewModel"/>
</Window.Resources>
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="Choice">
<MenuItem Header="Alpha"
IsCheckable="True"
Checked="MenuItemAlpha_Checked"
IsChecked="{Binding AlphaIsRecording, Mode=TwoWay}"/>
<MenuItem Header="Bravo"
IsCheckable="True"
Checked="MenuItemBravo_Checked"
IsChecked="{Binding BravoIsRecording, Mode=TwoWay}"/>
<MenuItem Header="Charlie"
IsCheckable="True"
Checked="MenuItemCharlie_Checked"
IsChecked="{Binding CharlieIsRecording, Mode=TwoWay}"/>
</MenuItem>
</Menu>
</DockPanel>
</Window>
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
private MainWindowViewModel _mainWindowViewModel = null;
public MainWindow()
{
InitializeComponent();
// get a reference to the binding sources so we can set the properties
_mainWindowViewModel = new MainWindowViewModel();
this.DataContext = _mainWindowViewModel;
}
private void MenuItemAlpha_Checked(object sender, RoutedEventArgs e)
{
_mainWindowViewModel.BravoIsRecording = false;
_mainWindowViewModel.CharlieIsRecording = false;
}
private void MenuItemBravo_Checked(object sender, RoutedEventArgs e)
{
_mainWindowViewModel.AlphaIsRecording = false;
_mainWindowViewModel.CharlieIsRecording = false;
}
private void MenuItemCharlie_Checked(object sender, RoutedEventArgs e)
{
_mainWindowViewModel.AlphaIsRecording = false;
_mainWindowViewModel.BravoIsRecording = false;
}
}
ViewModelBase.cs:
class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
MainWindowViewModel.cs:
class MainWindowViewModel : ViewModelBase
{
private bool _alphaIsRecording = false;
private bool _bravoIsRecording = false;
private bool _charlieIsRecording = false;
// Alpha
public bool AlphaIsRecording
{
get { return _alphaIsRecording; }
set
{
_alphaIsRecording = value;
OnPropertyChanged("AlphaIsRecording");
}
}
// Bravo
public bool BravoIsRecording
{
get { return _bravoIsRecording; }
set
{
_bravoIsRecording = value;
OnPropertyChanged("BravoIsRecording");
}
}
// Charlie
public bool CharlieIsRecording
{
get { return _charlieIsRecording; }
set
{
_charlieIsRecording = value;
OnPropertyChanged("CharlieIsRecording");
}
}
}
You are binding to AlphaIsChecked
and BravoIsChecked
but I don't see any such properties? Try to bind to BravoIsRecording
:
<MenuItem Header="Bravo"
IsCheckable="True"
Checked="MenuItemBravo_Checked"
IsChecked="{Binding
Source={StaticResource mainWindowViewModel},
Path=BravoIsRecording,
Mode=TwoWay}"/>
Also, a view model doesn't typically inherit from DependencyObject
and define dependency properties. Turn your properties into ordinary CLR properties and put a breakpoint in the setter of the BravoIsRecording
and it should get hit when you check the CheckBox
.