c# - WPF MenuItem.IsChecked 绑定(bind)不起作用

标签 c# wpf xaml wcf-binding

我有一个简单的菜单,并且希望绑定(bind) MenuItems 的 IsChecked 属性,以便稍后可以在后面的代码中操作它们。我在属性的 getter 和 setter 中设置了断点,但它们从未被击中。

我搜索了其他问题,但没有一个问题能解决我的问题。我创建了一个框架项目来演示我所看到的内容。

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

编辑:

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

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

最佳答案

您正在绑定(bind)到 AlphaIsCheckedBravoIsChecked,但我没有看到任何此类属性?尝试绑定(bind)到 BravoIsRecording:

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

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

关于c# - WPF MenuItem.IsChecked 绑定(bind)不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44159426/

相关文章:

c# - 在 UWP(通用 Windows 应用程序)、Windows 10 中创建自定义形状控件

.net - 在 Windows 8 Metro 风格的 c# 应用程序上捕获 Enter 和空格键

c# - 内部 StackPanel 不可见

WPF、MVVM 和异步工作

c# - 通过 COM 连接到第三方应用程序时出错 : mscorlib Exception from HRESULT: 0x80040202

c# - 读取Excel互操作单元格: Cannot convert mthod group 'ToString' to non-delegated type 'String' [closed]时出错

c# - Selenium 无法处理 IE 中的确认证书弹出窗口

c# - 如何防止 Microsoft Report Viewer 报告 (PDF) 中出现 "serrated"PNG 图像(锯齿)

c# - DataGrid WPF StackOverFlow 异常

c# - for 循环如何与堆栈溢出相关?