WPF MenuItem.IsChecked 绑定不起作用



我有一个简单的菜单,并希望绑定 MenuItems 的 IsChecked 属性,以便我以后可以在代码隐藏中操作它们。 我在属性的获取器和设置器中设置了一个断点,但它们从未被击中。

我搜索了其他问题,但没有一个对我的问题有任何启发。 我创建了一个骨架项目来演示我所看到的。

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
    }
}

主窗口视图模型.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); }
    }
}

编辑:

由于 mm8 提供的解决方案(POCO 而不是依赖项(,我修改了解决方案。 它现在用作一组三个菜单项,它们充当单选按钮。 代码如下:

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));
        }
    }
}

主窗口视图模型.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");
        }
    }
}

您绑定到AlphaIsCheckedBravoIsChecked但我没有看到任何此类属性?尝试绑定到BravoIsRecording

<MenuItem Header="Bravo"
        IsCheckable="True"
        Checked="MenuItemBravo_Checked"
        IsChecked="{Binding
        Source={StaticResource mainWindowViewModel},
        Path=BravoIsRecording,
        Mode=TwoWay}"/>

此外,视图模型通常不会继承自DependencyObject和定义依赖项属性。将您的属性转换为普通 CLR 属性,并在BravoIsRecording的 setter 中放置一个断点,当您检查CheckBox时,它应该会被命中。

最新更新