Создание INotifyPropertyChanged проксирует для диспетчеризации вызовов потоку UI

Я бы включил это в функции:

awk '
    function next_month(year, month) {
        month++;
        if (month == 13) {
            year++;
            month = 1;
        }
        return sprintf "%d-%02d", year, month;
    }

    function previous_month(year, month) {
        month--;
        if (month == 0) {
            year--;
            month = 12;
        }
        return sprintf "%d-%02d", year, month;
    }

    BEGIN {
        year = 2019; month = 1;
        printf "%d-%d\t%s\t%s\n",
            year, month,
            next_month(year, month),
            previous_month(year, month);

        year = 2018; month = 12;
        printf "%d-%d\t%s\t%s\n",
            year, month,
            next_month(year, month),
            previous_month(year, month);
    }
'
2019-1  2019-02 2018-12
2018-12 2019-01 2018-11

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

Удалите параметры функции, чтобы изменить переменные в глобальной области видимости.

7
задан Community 23 May 2017 в 12:11
поделиться

2 ответа

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

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

Чтобы использовать этот класс, вы хотели бы изменить свое привязку:

Bindings.Add("TargetProperty", new SyncBindingWrapper<PropertyType>(source, "SourceProperty"), "Value");

и вот синхронизация:

using System.ComponentModel;
using System.Reflection;
using System.Threading;

public class SyncBindingWrapper<T> : INotifyPropertyChanged
{
    private readonly INotifyPropertyChanged _source;
    private readonly PropertyInfo _property;

    public event PropertyChangedEventHandler PropertyChanged;

    public T Value
    {
        get
        {
            return (T)_property.GetValue(_source, null);
        }
    }

    public SyncBindingWrapper(INotifyPropertyChanged source, string propertyName)
    {
        _source = source;
        _property = source.GetType().GetProperty(propertyName);
        source.PropertyChanged += OnSourcePropertyChanged;
    }

    private void OnSourcePropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName != _property.Name)
        {
            return;
        }
        PropertyChangedEventHandler propertyChanged = PropertyChanged;
        if (propertyChanged == null)
        {
            return;
        }

        SynchronizationContext.Current.Send(state => propertyChanged(this, e), null);
    }
}
5
ответ дан 7 December 2019 в 05:22
поделиться

Не полагаясь на SynchrnoisationConext можно полагаться на ISynchronizeInvoke

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(string propertyName)
{
    var handler = PropertyChanged;
    if (handler != null)
    {
        var e = new PropertyChangedEventArgs(propertyName);
        foreach (EventHandler h in handler.GetInvocationList())
        {
            var synch = h.Target as ISynchronizeInvoke;
            if (synch != null && synch.InvokeRequired)
                synch.Invoke(h, new object[] { this, e });
            else
                h(this, e);
        }
    }
}
0
ответ дан 7 December 2019 в 05:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: