【问题标题】:Simplify mvvm objects WPF [duplicate]简化 mvvm 对象 WPF [重复]
【发布时间】:2017-01-18 00:30:26
【问题描述】:

我想简化我的类中的属性声明。问题在于 getter 和 setter 的定义。我对数百个属性做的完全一样。所有属性都是这样创建的,其中“LogPropertyChanged”方法也是 RaisePropertyChange。

public class PCS_MA_V1_ALARMSTAT : ViewModelBase
{
    private Boolean _ActionAlarmHighHigh;
    public Boolean ActionAlarmHighHigh
    {
        get
        {
            return _ActionAlarmHighHigh;
        }
        set
        {
            if(value!= _ActionAlarmHighHigh)
            {
                _ActionAlarmHighHigh = value;
                LogpropertyChanged("ActionAlarmHighHigh", oldVal, newVal);
            }

        }
    }
    private Boolean _ActionAlarmLowLow;
    public Boolean ActionAlarmLowLow
    {
        get
        {
            return _ActionAlarmLowLow;
        }
        set
        {
            if(value!= _ActionAlarmLowLow)
            {
                _ActionAlarmLowLow = value;
                LogpropertyChanged("ActionAlarmLowLow", oldVal, newVal);
            }

        }
    }
}

现在我认为这种语法非常复杂,而且使用起来非常麻烦。有没有办法可以像这样创建类:

public class PCS_MA_V1_ALARMSTAT: ViewModelBase
{
    public Boolean ActionAlarmHighHigh { get; set; }
    public Boolean ActionAlarmLowLow { get; set; }
}

然后监控实例。如果某个属性已更改,我会在该特定属性上运行 LogPropertyChanged。这可能吗?

【问题讨论】:

  • 你是今天第二个问这个问题的人。对你来说,答案也是“不”。人们在这里所做的是编写一个SetProperty<T>(ref T propertyField, [CallerMemberName] String propName = null) 方法,该方法设置字段并在值更改时引发PropertyChanged,并且它也可以记录。顺便说一句,我至少会将LogpropertyChanged 重命名为并不意味着它仅进行日志记录的名称。方法不错,但名称很容易误导。
  • 然后 write a snippet 创建属性定义,如果您使用的是 Visual Studio。
  • @EdPlunkett 我已经创建了一个生成这些类的程序。它创建了数千行。问题是现在我还必须维护该应用程序... ;) 如果您有时间,我会非常感谢您在代码中的回答。我不知道如何用你的方法来实现它。
  • Here's an example 如何使用面向方面的编程将冗余重构为简单的属性。不过,如果您不熟悉属性和 AOP,我认为可能很难掌握。据我所知,没有包含这些属性的库。

标签: c# wpf mvvm properties


【解决方案1】:

很遗憾,您无法覆盖 getset 的默认行为。

你能做的就是像这样写一个ViewModelBase。这是一个常见的成语。我下面的代码大部分是被盗的from this answer,而Prism 的BindableBasea similar SetProperty<T> method,但我没有去寻找它们的实现。不可能有那么多。

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace HollowEarth.MVVM
{
    public class ViewModelBase : INotifyPropertyChanged
    {
        #region SetProperty
        protected virtual bool SetProperty<T>(ref T backingField, 
            T newValue, 
            [CallerMemberName] String propName = null)
        {
            if (EqualityComparer<T>.Default.Equals(backingField, newValue))
            {
#if DEBUG
                System.Diagnostics.Trace.WriteLine(
                    $"No change in {propName} == {backingField}");
#endif
                return false;
            }

#if DEBUG
            System.Diagnostics.Trace.WriteLine(
                $"Changing {propName} from {backingField} to {newValue}");
#endif

            backingField = newValue;
            OnPropertyChanged(propName);

            return true;
        }
        #endregion SetProperty

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(
            [CallerMemberName] String propName = null)
        {
            PropertyChanged?.Invoke(this, 
                new PropertyChangedEventArgs(propName));
        }
        #endregion INotifyPropertyChanged
    }
}

然后像这样使用它:

public class MyViewModel : ViewModelBase
{
    #region Whenever Property
    private DateTime? _whenever = default(DateTime?);
    public DateTime? Whenever
    {
        get { return _whenever; }
        set { SetProperty(ref _whenever, value); }
    }
    #endregion Whenever Property
}

我写Visual Studio snippets 来生成属性。您说您正在以编程方式生成所有这些东西,因此 sn-ps 不是即时要求,但要记住这一点。

另一种可能性,如果生成代码的可维护性是一个问题,使用部分类。将生成的代码放在从不手动编辑的单独文件中(很像 winforms 中的 Form1.Designer.cs/Form1.resx),并维护用于生成这些文件的 input 文件。将您的生成器设置为任何输入文件的构建操作。

对于可维护性主题的元级俏皮话,请用 Perl 编写分部类生成器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-30
    • 2015-06-04
    • 1970-01-01
    • 2011-07-26
    • 2015-03-21
    • 1970-01-01
    • 2022-10-06
    • 2012-12-16
    相关资源
    最近更新 更多