繁体   English   中英

试图做两种方式绑定 INotifyPropertyChanged null

[英]Trying to do two way binding INotifyPropertyChanged null

应该发生的是,由于计时器,我拥有的复选框会来回闪烁。 变量改变,但形式不变。 两边都勾选了dataMember的名字。

旨在与此处的 INotifyPropertyChanged 实现类似的类: 实现 INotifyPropertyChanged - 是否存在更好的方法?

using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace Notice
{
    public class Notifier : INotifyPropertyChanged
    {
        //used to prevent infinite loops
        private bool controllerChanged;
        public event PropertyChangedEventHandler PropertyChanged;
        public Notifier()
        {
            controllerChanged = false;
        }
        public bool SetField<T>(ref T field, T value, string propertyName)
        {
            if (!controllerChanged)
            {
                controllerChanged = true;
                if (EqualityComparer<T>.Default.Equals(field, value))
                {
                    controllerChanged = false;
                    return false;
                }
                field = value;
                OnPropertyChanged(propertyName);
                controllerChanged = false;
                return true;

            }
            return false;
        }

        protected virtual void OnPropertyChanged(string property)
        {
            //PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));

            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(property));
            }

        }

    }
}

类变量,仅举一个例子

using System;
using Notice;

namespace Vars
{
    public class Checks
    {

        private bool checkbox;

        Notifier note = new Notifier();
        public Checks()
        {
            checkbox = true;

        }

        public bool Checkbox 
        { 
            get { return checkbox; }
            //set { WindowsFormsApp1.Program.note.SetField(ref checkbox, value, "Checkbox"); }
            set { note.SetField(ref checkbox, value, "Checkbox"); }
        }


    }
}

大部分表单代码:

public Form1()
        {
            InitializeComponent();
            //If you bind it using properties for the item in the form, don't need this line
            checkBox1.DataBindings.Add("Checked", WindowsFormsApp1.Program.Ch, "Checkbox", true, DataSourceUpdateMode.OnPropertyChanged);
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            WindowsFormsApp1.Program.Ch.Checkbox = !WindowsFormsApp1.Program.Ch.Checkbox;
            Console.WriteLine(WindowsFormsApp1.Program.Ch.Checkbox);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            WindowsFormsApp1.Program.Ch.Checkbox = !WindowsFormsApp1.Program.Ch.Checkbox;
            Console.WriteLine(WindowsFormsApp1.Program.Ch.Checkbox);
        }

虽然“更喜欢组合而不是继承”这句话经常出现,但在这里你已经走得太远了。

INotifyPropertyChanged接口依赖于事件的sender是属性本身所在的同一对象。 在您的实现中,您已将事件委托给一个根本不向公众公开的对象,即使 XAML 可以从该对象接收通知,该对象也不是属性所在的对象。

你应该:

  1. Make Checks继承Notifier类而不是组合一个
  2. SetField()方法设置为protected而不是public ,并直接从属性 setter 中调用它,而不是通过Notifier的中间实例

就其价值而言,通常不需要您添加到规范实现中的controllerChanged功能。 不会发生递归,因为当设置的值与当前值相同时不会发出通知。 如果您遇到递归问题,您可能正在做其他不正确的事情,例如尝试切换值以响应通知。 在这种情况下,将递归短路可避免堆栈溢出,但会隐藏导致它的代码中的真正错误。

我建议也删除controllerChanged功能。 如果没有它的代码有问题,请发布一个新问题,确保包含一个可靠地重现堆栈溢出的良好 [mcve],解释您已经尝试过的修复方法,以及您具体需要什么帮助和。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM