如何为我的 bool 属性正确实现 INotifyPropertyChanged 并绑定到 CheckBox.IsChecked?

2024-03-15

这里是新手。我一直在尝试围绕数据绑定进行思考,并想尝试将视图中的复选框双向绑定到我称为“State”的单独类中的布尔值。关键是要确保它们始终保持同步。

因此,我在视图中创建了一个复选框,并将其绑定到前面提到的 State 类中的布尔属性,并附有一个绕过该复选框并直接切换布尔属性的按钮(恰当地标记为“Ninja!”)。重点是测试属性更改时复选框的数据绑定是否做出反应。但是,我无法尽我所能弄清楚当属性更改时应该如何调用 OnPropertyChanged 方法。

这是我到目前为止所拥有的:

<CheckBox x:Name="checkBox" Content="CheckBox" HorizontalAlignment="Left" Margin="232,109,0,0" VerticalAlignment="Top" IsChecked="{Binding Checked, Mode=TwoWay}"/>
<Button x:Name="button" Content="Ninja!" HorizontalAlignment="Left" Margin="228,182,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>

我编写的“State”类的代码:

namespace TestTwoWayBinding
{
    class State : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private bool _checked;
        public bool Checked {
            get
            {
                return _checked;
            }
            set
            {
                _checked = value;
                OnPropertyChanged(Checked);
            }
        }       

        public void Toggle()
        {
            if (!Checked)
            {
                Checked = true;
            }
            else
            {  
                Checked = false;

            }
        }

        public State(bool c)
        {
            this.Checked = c;
        }

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if(PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(Checked));
            }
        }
    }
}

以及视图上用于初始化和处理事件的代码隐藏:

namespace TestTwoWayBinding
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private State _state;
        public MainWindow()
        {            
            InitializeComponent();
            _state = new State((bool)checkBox.IsChecked);
        }

        private void button_Click(object sender, RoutedEventArgs e)
        {
            _state.Toggle();
        }
    }
}

据我所知,OnPropertyChanged 需要一个 String propertyName,但我不知道这会带来什么。当我输入属性名称(Checked)时,它自然指的是布尔值,而不是字符串。我没有得到什么?我还做错了什么,因为当我通过按钮更改属性时,复选框没有注册属性更改?


建议您传递字符串文字的两个答案"Checked"会起作用,但恕我直言,这不是最好的方法。相反,我更喜欢使用[CallerMemberName]当实施OnPropertyChanged()方法。 (我不知道第三个答案是关于什么的……它似乎与这个问题没有任何关系,我猜它只是从其他地方复制/粘贴的)。

这是我如何写你的例子State class:

class State : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private bool _checked;
    public bool Checked
    {
        get { return _checked; }
        set { _checked = value; OnPropertyChanged(); }
    }       

    public void Toggle()
    {
        Checked = !Checked;
    }

    public State(bool c)
    {
        this.Checked = c;
    }

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

这里的关键是标记为的参数[CallerMemberName]只需不传递任何值,就会自动填充调用者的正确值。默认值为null是否存在这样编译器将允许调用者不传递值。

请注意,我还简化了Toggle()方法。没有必要使用if改造一的声明bool价值转化为他人;这就是布尔运算符的用途。

我也改变了OnPropertyChanged()方法,以便它是线程安全的,即如果某些代码取消订阅最后一个处理程序,则不会崩溃PropertyChanged事件字段与事件字段进行比较的时间之间的事件null以及事件实际引发的时间。通常,这不是问题,因为这些属性几乎总是仅从单个线程访问,但很容易防范,并且是一个好习惯。

请注意,在 C# 6 中,您可以选择只编写PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));对于方法体。并不是每个人都 100% 地使用新的编译器,所以我只是将其作为您的可选选择。

当然,你还需要设置DataContext正确,如图所示其他答案之一 https://stackoverflow.com/a/36971642:

public MainWindow()
{
    InitializeComponent();
    _state = new State((bool)checkBox.IsChecked);
    this.DataContext = _state;
}

不过,就我个人而言,我不确定我是否会为构造函数烦恼。您似乎没有其他代码可以设置checkBox.IsChecked,所以在我看来,无论如何你总是会得到默认值。此外,如果视图模型类没有参数化构造函数,则无法在 XAML 中创建视图模型类。将来,您可能更愿意配置您的DataContext像那样。例如。:

<Window.DataContext>
  <l:State Checked="True"/>
</Window.DataContext>

在窗口的构造函数中:

public MainWindow()
{
    InitializeComponent();
    _state = (State)this.DataContext;
}


另请参阅相关问答自动 INotifyPropertyChanged https://stackoverflow.com/q/527602。那里的问题确实是关于不同的东西 - 他们想要实现接口,而不必在属性设置器中显式编写任何内容 - 但无论好坏,他们得到的答案实际上更多的是关于您的场景,这只是一个问题简化属性设置器实现而不是使其完全自动化。

我不得不承认,我本以为已经有另一个问题可以将您的问题标记为重复项。而且我确实找到了很多related问题。但没有什么直接关注“我如何实现和使用实现INotifyPropertyChanged?”,这确实是你的问题。


Addendum:

我做了一些更多的搜索,虽然这些似乎都不会被认为是完全重复的,但它们都有很好的信息,可以帮助解决有关实施的问题INotifyPropertyChanged:

属性的使用... INotifyPropertyChanged https://stackoverflow.com/q/1662745
模型和视图模型的 INotifyPropertyChanged https://stackoverflow.com/q/23359154
BindableBase 与 INotifyChanged https://stackoverflow.com/q/28844518
如何在 MVVM (WPF) 中编写“ViewModelBase” https://stackoverflow.com/q/36149863

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何为我的 bool 属性正确实现 INotifyPropertyChanged 并绑定到 CheckBox.IsChecked? 的相关文章

随机推荐

  • 如何在页面刷新/加载时刷新验证码图像?

    我想强制我的网站在每次加载时刷新验证码图像 因此我有一个由 onload 事件触发的 javascript 方法 这里我有以下行 document getElementById yw0 button click Firebug 没有检测到任
  • 高效地按行应用函数

    我有一个包含多个列的数据框 其中包含一个诊断的信息 条目是TRUE FALSE or NA 我创建了一个向量 将这些列总结如下 如果患者在某个时间被诊断出来 TRUE then TRUE 如果唯一有效的条目是FALSE then FALSE
  • 如何在SWI-Prolog中启用所有统一中的发生检查?

    根据维基百科 https en wikipedia org wiki Occurs check 为所有统一提供声音统一的实现是 Qu Prolog 和 Strawberry Prolog 以及 可选地 通过运行时标志 XSB SWI Pro
  • 如何使我的 SVG 移动设备具有响应能力

    我想为网站制作 svg 动画 但 svg 不支持移动响应 它延伸出背景 从而使网站的宽度超出了我的预期 我认为很可能我在视口或宽度和高度上做错了什么 但我不知道哪里出了问题 此外 当我将 chrome 浏览器最小化到移动屏幕宽度尺寸时 它在
  • 所需的 Bluemix Analytics for Apache Spark 日志文件信息

    我在调试我的 Spark 笔记本时想要更多信息 我找到了一些日志文件 ls HOME notebook logs 这些文件是 bootstrap nnnnnnnn nnnnnn log jupyter nnnnnnnn nnnnnn log
  • 矩阵到欧拉角

    我正在尝试从旋转矩阵中提取欧拉角 我的约定 矩阵列主 坐标系右手 正角右手 旋转顺序 YXZ 首先是航向 然后是姿态 然后是倾斜 我发现了这个 但无法使用它 因为它们使用其他轴顺序 http www euclideanspace com m
  • 我应该使用 Eclipse 插件(或 OSGi Bundles)作为普通的依赖管理工具吗?

    它再次发生了 我加入了一个新项目 该项目由几个具有相互依赖性的普通 Eclipse Java 项目组成 所有项目都通过项目构建路径进行管理 我发现这一切有点混乱 当谈到运行配置时 你就进入了地狱 过去 我一直坚持创建插件项目 而不是普通的
  • 在 Vuejs 中使用 mixins

    我目前正在学习如何使用 Vuejs 开发应用程序 我有一个 main js 文件 其中包含用于设置 Vue js 的代码 我使用新文件 api js 创建了一个新目录 mixins 我想将其用作 mixin 以便每个组件都可以使用函数来访问
  • 为什么 git 一直告诉我它是“在后台自动打包存储库以获得最佳性能”?

    Note I don t认为这是重复的这个问题 https stackoverflow com questions 8633981 what does auto packing the repository for optimum perf
  • 如何使用反射(镜像)来访问 Dart 类中的方法名称?

    我需要 获取 Dart 类中的方法 我怎样才能做到这一点 我希望能够调用这些方法 我可以看一个例子吗 这是一个简单的可复制粘贴代码示例 import dart mirrors import dart io main var im refle
  • 使用 ajax 时 csrf 令牌无效

    我开始学习NodeJs在我对 js 的了解的推动下 我开始编写一些代码来创建用户注册逻辑 基本上我已经配置了ExpressJS通过以下方式 const express require express const app express co
  • 无法重新绑定滚动事件?

    我想在ajax调用中重新绑定窗口滚动事件 window scroll function column height first column height screenTop window scrollTop window height w
  • Python正则表达式不匹配

    这是我确信我错过了一些简单内容的事情之一 但是 在下面的示例程序中 我尝试使用 Python 的 RE 库来解析字符串 line 以获取浮点百分号之前的数字 即 90 31 但代码总是打印 不匹配 我也尝试了其他几个正则表达式 所有结果都相
  • 方法名称是否隐式转换为委托类型?

    我在理解代表方面有点困难 我有一个委托 当输入 y 字符时我将调用它 public delegate void respondToY string msgToSend private respondToY yHandler 我有一个订阅方法
  • Clojure 蛇跳过位置

    我是 Clojure 初学者 我一直在玩这里介绍的贪吃蛇游戏代码https github com stuarthalloway programming clojure blob master src examples snake clj h
  • 如何在 Windows 上的 Firefox 中阻止 Flash 内容透过 jQuery UI 对话框

    我正在使用 jQuery UI 对话框 在 Windows 上的 IE 和 FF 中 我通过对话框获取底层 Flash 内容 我通过启用 IE 解决了这个问题bgiframejQuery 对话框窗口上的选项并更改bgiframe脚本适用于任
  • 如何从 Mesos 框架 Scheduler 类读取 mesos 任务 stdout/stderr?

    我正在开发一个 Mesos 框架 它工作得很好 我唯一的问题是我无法从 Scheduler 类内部读取任务 stdout 或 stderr 我在下面提供了一个代码示例 我想读取已完成任务的标准输出和标准错误 最好在 statusUpdate
  • 10e 表示法与变量一起使用吗?

    我想知道如何在 python 2 7 9 中使用变量的 10eX 表示法 就文字而言 10eX 给出 10 X 00000 浮点数 然而 我想使用一些变量而不是文字 但它不起作用 如果可以的话 我应该进行什么语法更改或者是否有其他方法可以这
  • 代码块、单个项目、许多可执行文件

    I use 代码 块 http en wikipedia org wiki Codeblocks和 C 我的项目应该构建多个可执行文件 一组使用共享库的小工具 如何设置 CB 生成多个二进制文件 每个二进制文件都有自己的main 看看Cod
  • 如何为我的 bool 属性正确实现 INotifyPropertyChanged 并绑定到 CheckBox.IsChecked?

    这里是新手 我一直在尝试围绕数据绑定进行思考 并想尝试将视图中的复选框双向绑定到我称为 State 的单独类中的布尔值 关键是要确保它们始终保持同步 因此 我在视图中创建了一个复选框 并将其绑定到前面提到的 State 类中的布尔属性 并附