订阅ObservableCollection项属性更改 - WPF

3

我需要订阅列表中对象的属性。我找到了这个例子 (https://dev59.com/rXbZa4cB1Zd3GeqPJLyE#18770397),它很完美地工作,但如果我向列表中添加一个新元素,它就无法正常工作。有什么解决方案吗?谢谢!

编辑

IDisposable subscription =
    Observable
        .FromEventPattern
            <NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
                x => MyList.CollectionChanged += x,
                x => MyList.CollectionChanged -= x)
        .Where(x => x.EventArgs.Action == NotifyCollectionChangedAction.Add)
        .SelectMany(x => x.EventArgs.NewItems.Cast<MyCustomClass>())
        .SelectMany(x =>
        {
            CallMethodWhenAddItem(x);
            return x.OnPropertyChange(nameof(x.MyCustomProperty));
        })
        .Subscribe(x =>
            // x is PropertyChangedEventArgs, not MyCustomClass
            if (x.MyCustomProperty == "SomeValue") {
                RunAction();
            }
        });


public static IObservable<PropertyChangedEventArgs> OnPropertyChange<T>(this T currentSource, string propertyName)
    where T : INotifyPropertyChanged
{
    return
        Observable
            .FromEventPattern
                <PropertyChangedEventHandler, PropertyChangedEventArgs>(
                    eventHandler => eventHandler.Invoke,
                    x => currentSource.PropertyChanged += x,
                    x => currentSource.PropertyChanged -= x)
            .Where(x => x.EventArgs.PropertyName == propertyName)
            .Select(x => x.EventArgs);
}

您能否对以下问题提供一些指导?

1) 使用"eventHandler => eventHandler.Invoke"和不使用它有什么区别。互联网上的许多示例使用它,而其他示例则不使用它。我真的看不出有什么区别。

2) 如何取消订阅动态添加的属性。只需要从列表中删除它吗?

谢谢!

1个回答

1

System.Func<EventHandler<TEventArgs>, TDelegate> 参数用于将给定的事件处理程序转换为与底层 .NET 事件兼容的委托。如果不需要,请不要使用它。它通常用于连接非标准事件处理程序。

永远不要进行嵌套订阅。这样你就不需要担心内部订阅的释放问题。请按照以下方式编写查询:

IDisposable subscription =
    Observable
        .FromEventPattern
            <NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
                x => MyList.CollectionChanged += x,
                x => MyList.CollectionChanged -= x)
        .Where(x => x.EventArgs.Action == NotifyCollectionChangedAction.Add)
        .SelectMany(x => x.EventArgs.NewItems.Cast<MyCustomClass>())
        .SelectMany(x =>
        {
            CallMethodWhenAddItem(x);
            return x.OnPropertyChange(nameof(x.MyCustomProperty));
        })
        .Subscribe(_ => { });

根据评论更新:
void Main()
{
    var MyList = new ObservableCollection<int>();

    IDisposable subscription =
        Observable
            .FromEventPattern
                <NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
                    x => MyList.CollectionChanged += x,
                    x => MyList.CollectionChanged -= x)
            .Where(x => x.EventArgs.Action == NotifyCollectionChangedAction.Add)
            .SelectMany(x => x.EventArgs.NewItems.Cast<MyCustomClass>())
            .SelectMany(x =>
            {
                CallMethodWhenAddItem(x);
                return x.OnPropertyChange(nameof(x.MyCustomProperty));
            })
            .Where(x => x.MyCustomProperty == "SomeValue")
            .Subscribe(_ => { });
}

public static class Ex
{
    public static IObservable<T> OnPropertyChange<T>(this T currentSource, string propertyName)
        where T : INotifyPropertyChanged
    {
        return
            Observable
                .FromEventPattern
                    <PropertyChangedEventHandler, PropertyChangedEventArgs>(
                        eventHandler => eventHandler.Invoke,
                        x => currentSource.PropertyChanged += x,
                        x => currentSource.PropertyChanged -= x)
                .Where(x => x.EventArgs.PropertyName == propertyName)
                .Select(x => currentSource);
    }
}

public class MyCustomClass : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public string  MyCustomProperty { get; set; }
}

public void CallMethodWhenAddItem(MyCustomClass x) { }

谢谢您的帮助。我有一个关于这个实现的问题。在我写的例子中,有一些我认为不相关的东西被省略了。当一个元素被添加到集合中时,我会调用一个方法(我修改了示例)。在这种情况下,正确的实现方式是什么?谢谢! - avechuche
我找到了我认为你认为的问题。在订阅中,我需要访问更改属性的对象。在我的原始实现中,变量X是完整的对象(MyCustomClass)。在这个例子中,订阅变量是"PropertyChangedEventArgs"类型。我编辑了这个例子以便更好地理解。 - avechuche
我想我试图修改他的答案而不是我的示例。没有注意到 :) - avechuche
@avechuche - 你的意思是需要更改 OnPropertyChange 的返回类型并在查询中添加 .Where 子句,对吗? - Enigmativity
@avechuche - 这是微不足道的更改。你能做到吗? - Enigmativity
显示剩余5条评论

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