优雅的方式在多个控件中实现INotifyPropertyChanged

4

我正在构建一个WPF应用程序,逐渐发现使用WPF的乐趣和挫折。我的最新问题涉及使用INotifyPropertyChanged更新UI。

我的应用程序具有堆叠的UserControl,每个UserControl包含多个控件,因此总共有数百个控件每秒更新提供实时数据。为了更新所有控件,我正在使用类似下面的代码,目前它可以按预期工作。

namespace ProjectXAML
{
    public partial class ProjectX : UserControl, INotifyPropertyChanged
    {


#region Declare Getter/Setter with INotifyPropertyChanged groupx3

        private string m_group1Text1;
        public string group1Text1
        {
            get
            {
                return m_group1Text1;
            }
            set
            {
                m_group1Text1 = value;
                NotifyPropertyChanged("group1Text1");
            }
        }

        private string m_group1Text2;
        public string group1Text2
        {
            get
            {
                return m_group1Text2;
            }
            set
            {
                m_group1Text2 = value;
                NotifyPropertyChanged("group1Text2");
            }
        }

        private string m_group2Text1;
        public string group2Text1
        {
            get
            {
                return m_group2Text1;
            }
            set
            {
                m_group2Text1 = value;
                NotifyPropertyChanged("group2Text1");
            }
        }

        private string m_group2Text2;
        public string group2Text2
        {
            get
            {
                return m_group2Text2;
            }
            set
            {
                m_group2Text2 = value;
                NotifyPropertyChanged("group2Text2");
            }
        }

        private string m_group3Text1;
        public string group3Text1 
        { 
            get
            {
                return m_group3Text1;
            }
            set
            {
                m_group3Text1 = value;
                NotifyPropertyChanged("group3Text1");
            }
        }

        private string m_group3Text2;
        public string group3Text2
        {
            get
            {
                return m_group3Text2;
            }
            set
            {
                m_group3Text2 = value;
                NotifyPropertyChanged("group3Text2");
            }
        }

 #endregion

 #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        /// Notifies the property changed.
        private void NotifyPropertyChanged(string property)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }
 #endregion

}
}

我的问题是:

  1. 有没有更优雅的方式来提高PropertyChanged事件,而不是大量的get/set代码?

  2. 有没有一种方法可以引发1个PropertyChanged事件,覆盖包含多个控件的整个,而不是为每个控件分别创建一个事件? 有没有更好的方法比我正在尝试的方法?


1
如果您执行NotifyPropertyChanged(null);,则会通知INotifyPropertyChanged的监听器对象上的所有属性已更改。 - Colin Smith
@HenkHolterman - 这不是模型的一部分。这段代码设置/获取字符串,这些字符串与位于按钮内部的TextBlock绑定。 - user857521
@colinsmith - 谢谢 Colin。你的建议在我的实例中运行良好。那是否是正确的做事方式呢?我一定需要更多地阅读 MVVM,因为每个人都在建议。 - user857521
这实际上意味着它只用作源。但是当您将其移动到虚拟机时,您的生活将变得更加轻松。 - H H
它们都已更新,所以我认为在这种情况下是合理的...至少目前是这样。如果您将其作为答案,我会接受,因为我认为它可能回答了我的具体问题。现在开始阅读一些虚拟机相关内容... - user857521
显示剩余7条评论
3个回答

4

针对你问题中的这一部分:“有没有办法触发一个PropertyChanged事件,覆盖包含它的整个UserControl。”

是的,你可以触发一个PropertyChanged通知,它表示我的对象上的所有属性都已更新。

使用:

NotifyPropertyChanged(null);

这会通知INotifyPropertyChanged监听器对象的所有属性已经更改。

通常情况下不建议使用此功能,因为它可能被滥用,并导致效率低下的更新,例如如果您只更改了几个属性并使用该功能。

但是,如果您的对象拥有很多属性,而且您总是同时更改这些属性,那么可以考虑使用此功能,并将许多单独的通知合并为一个在修改所有属性后触发的通知。

示例使用场景(假设您正在以某种方式更新所有群组):

void UpdateAllGroupTextProperties()
{
    group1Text1 = "groupA";
    group1Text2 = "groupA2";
    group2Text1 = "groupB";
    group2Text2 = "groupB2";
    group3Text1 = "groupC";
    group3Text2 = "groupC2";
    NotifyPropertyChanged(null);
}

4

如果您使用的是VS 2012,则可以按照以下步骤进行:

private void SetProperty<T>(ref T field, T value, [CallerMemberName] string name = "")
{
    if (!EqualityComparer<T>.Default.Equals(field, value))
    {
        field = value;
        var handler = PropertyChanged;
        if (handler != null)
        {
          handler(this, new PropertyChangedEventArgs(name));
        }
    }
}

然后,您可以使用set属性方法,而无需硬编码属性的名称。

请注意,上面的代码是以下链接的例外 http://danrigby.com/2012/03/01/inotifypropertychanged-the-net-4-5-way/


3

使用设计模式模型视图控制器。因此,模型将为您提出更改。与MVVM一起,控件将使用其依赖对象自动查看更改并查看它们。


这个答案有什么问题吗?这是一个非常通用的问题,可以通过设计模式来解决。 - rekire
他正在询问如何避免在各处重复调用NotifyPropertyChanged() - SLaks
但实际上,OP的设置看起来很奇怪,MVVM可能是一个不错的提示。 - H H

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接