Краткий способ определения свойств для привязки данных MVVM в C # WPF - PullRequest
4 голосов
/ 28 августа 2009

Есть ли краткий способ определения свойств в ViewModel для привязки данных в C # WPF? Следующее определение свойства очень многословно, особенно когда свойств много:

private bool mSomeProperty;

public bool SomeProperty
{
    get { return this.mSomeProperty; }
    set
    {
        if (value != this.mSomeProperty)
        {
            this.mSomeProperty = value;
            OnPropertyChanged(new PropertyChangedEventArgs("SomeProperty"));
        }
    }
}

Ответы [ 7 ]

3 голосов
/ 28 августа 2009

В C # мне нравится создавать базовый класс и добавлять в него несколько вспомогательных методов. Затем я заставляю мои ViewModels спускаться с него. Это из памяти, но это примерно так:

public class Observable : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void SetProperty<T>(ref T backingField, T newValue,
        string propertyName)
    {
        if (Equals(backingField, newValue))
            return;
        backingField = newValue;
        if (PropertyChanged != null)
        {
            PropertyChanged(this,
                new PropertyChangedEventArgs(propertyName));
        }
    }
}

И, при использовании:

public class MyClass : Observable
{
    private bool m_someProperty;

    public bool SomeProperty
    {
        get { return m_someProperty; }
        set { SetProperty(ref m_someProperty, value, "SomeProperty"); }
    }
}
2 голосов
/ 29 августа 2009

Вы можете найти некоторые идеи здесь:

Внедрение и использование INotifyPropertyChanged https://github.com/jbe2277/waf/wiki/Implementing-and-usage-of-INotifyPropertyChanged

1 голос
/ 28 августа 2009

Вы всегда можете использовать DependencyProperties и поддержать свое сердце ...

0 голосов
/ 10 января 2019

Этот ответ очень похож на ответ Джо Уайта, приведенный выше, но код немного более краткий и, возможно, немного более понятный, поскольку имена свойств не нужно передавать в виде строки в кавычках.

Используя функциональность CallerMemberName , можно сделать это двумя способами. Одним из них является создание абстрактного класса, который содержит код IPropertyNotifyChanged , а другой подход - включение кода поддержки IPropertyNotifyChanged в текущий класс. Я обычно использую оба в зависимости от контекста.

Вот как выглядят результаты при использовании абстрактного класса:

public abstract class PropertyNotifier: INotifyPropertyChanged
{
    #region INotifyPropertyChanged support code
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected bool SetProperty<T>(ref T storage, T value,
        [CallerMemberName] String propertyName = null)
    {
        bool result = false;

        if (!Object.Equals(storage, value))
        {
            storage = value;
            OnPropertyChanged(propertyName);
            result = true;
        }
        return result;
    }
    #endregion INotifyPropertyChanged support code
}

И в использовании:

public interface IPerson
{
    String FirstName { get; set }
    String LastName { get; set }
}

public class Person : PropertyNotifier, IPerson
{
    private string _FirstName;
    private string _LastName;

    public String FirstName
    {
        get { return _FirstName; }
        set { SetProperty(ref _FirstName, value); }
    }

    public String LastName
    {
        get { return _LastName; }
        set { SetProperty(ref _LastName, value); }
    }
}

Надеюсь, это поможет!

0 голосов
/ 28 августа 2009

Вы можете рассмотреть PostSharp , который позволит вам декорировать свойство (которое затем можно переопределить как автоматическое свойство) и вставить в установщик строку, которая запускает событие NotifyPropertyChanged. Дополнительным преимуществом является избавление от строки, совпадающей с именем свойства.

Он не идеален, потому что вам нужен этот инструмент, и он не будет сразу очевиден, если вы посмотрите на код позже, но он определенно делает его более аккуратным.

Я надеялся, что MSFT добавит такой атрибут в C # 4, но я думаю, нам придется ждать C # 5, если вообще.

0 голосов
/ 28 августа 2009

Я думаю, что вы не получите декларацию свойства намного меньше, чем, по крайней мере, с "нормальными" способами. Вы можете использовать перехватчик замка, чтобы позаботиться о происшествии.

public class MyViewModel : INotifyPropertyChanged
{
    public event PropertyChanged;
    public void FirePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null) PropertyChanged(propertyName);
    }

    public virtual string MyProperty { get; set; }
    public virtual string MyProperty2 { get; set; }
}

Перехватчику потребуется запустить событие изменения свойства:

public class PropertyChangedInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        //Pseudo code
        if (invocation.Method is Property Setter)
        {
            Call FirePropertyChanged of invocation.InvocationTarget ;
        }
    }
}

Вам просто нужно убедиться, что свойства модели представления являются виртуальными, а модель представления всегда является прокси, а не самой моделью представления.

С наилучшими пожеланиями

0 голосов
/ 28 августа 2009

Если вы используете язык Delphi Prism (язык .NET на основе Pascal), вы просто добавляете ключевое слово notify, и компилятор автоматически реализует INotifyPropertyChanged и записывает для вас весь шаблон :

property SomeProperty: bool; notify;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...