C# 有没有一种方法可以指定可观测的初始值?

C# 有没有一种方法可以指定可观测的初始值?,c#,wpf,reactiveui,C#,Wpf,Reactiveui,在reactiveui和reactiveextensions中,您可以将多个观测值组合成一个。使用诸如CombineTest或Zip之类的函数,您可以使生成的可观察对象使用函数根据组合可观察对象的值计算结果。尽管CombineTest为您提供了一个observable,它在每次触发任何组合observable时都会通知您,但只有当所有这些observable至少触发一次时,它才会开始工作。我希望它从一开始就发出通知——给组合的可观测值一个初始值,或者别的什么。当然,我可以通过某种方式让那些可观察

在reactiveui和reactiveextensions中,您可以将多个观测值组合成一个。使用诸如CombineTest或Zip之类的函数,您可以使生成的可观察对象使用函数根据组合可观察对象的值计算结果。尽管CombineTest为您提供了一个observable,它在每次触发任何组合observable时都会通知您,但只有当所有这些observable至少触发一次时,它才会开始工作。我希望它从一开始就发出通知——给组合的可观测值一个初始值,或者别的什么。当然,我可以通过某种方式让那些可观察到的火焰设定初始值。但有时这并不是那么容易,或者会让代码看起来很难看。下面是一个例子: 我正在使用reactiveui制作一个wpf应用程序。在我的一个视图模型中,我试图通过组合观测值来创建属性。因此,我有一个具有NumberToSum属性的对象集合(ReactiveList),我需要一个用于显示该属性值总和的属性。该集合中的对象也是视图模型,用户可以更改其NumberToSum属性。求和的对象数由其他属性确定。我就是这样做的:

private readonly ReactiveList<Element> _collection = new ReactiveList<Element>();
private readonly ObservableAsPropertyHelper<int> _sum;
private int _elementsToTake = 0;

public int ElementsToTake
{
    get { return _elementsToTake; }
    set { this.RaiseAndSetIfChanged(ref _elementsToTake, value) }
}

public int Sum
{
    get { return _sum.Value; }
}

public MyViewModel
{
    var elementsToTakeObservable = this
        .WhenAny(x => x.ElementsToTake, x => x.Value);
    _collection.ChangeTrackingEnabled = true;
    //here I'm adding some objects to _collection
    var sumObservable = _collection.ItemChanged
        .CombineLatest(elementsToTakeObservable,
            (_, c) => _collection.Take(c)
                .Aggregate(0, (i, x) => i + x.NumberToSum))).
        .ToProperty(this, x => x.Sum, out _sum, 0);
}
private readonly ReactiveList _collection=new ReactiveList();
私有只读ObservablesPropertyHelperSum;
私有int _elementsToTake=0;
公共int元素STOTAKE
{
获取{return\u elementsToTake;}
设置{this.RaiseAndSetIfChanged(ref_elementsToTake,value)}
}
公共整数和
{
获取{return\u sum.Value;}
}
公共MyViewModel
{
var elementsToTakeObservable=this
.WhenAny(x=>x.ElementsToTake,x=>x.Value);
_collection.ChangeTrackingEnabled=true;
//在这里,我将向_集合添加一些对象
var sumObservable=\u collection.ItemChanged
.CombineTest(元件可观测,
(u,c)=>_集合。取(c)
.聚合(0,(i,x)=>i+x.NumberToSum)))。
.ToProperty(this,x=>x.Sum,out\u Sum,0);
}
因此,我使用ReactiveList.ItemChanged来跟踪_集合项中的更改。每次发生变化时,将重新计算总和。这里的问题是将可观测值的初始值组合成可观测值。我可以通过为ElementsToTake属性赋值来轻松设置elementsToTakeObservable的初始值,这将引发属性更改事件和内容。但是对于_collection.ItemChanged-observable来说,这并不容易。我需要使_集合中的至少一个对象引发propertychanged事件,但这看起来很糟糕。
是否可以设置这些初始值?或者可能我做得完全不对?

StartWith
会解决您的问题。另外,我不确定您是否希望ItemChanged,它会在列表中的项目发生更改时发出信号,而不是在添加或删除项目时发出信号。在这里,您可能还想听听
Changed

虽然试图以这种方式保持“运行总数”很有诱惑力,但由于重置和移动,实际上很难做到这一点。更简单的方法是滥用CPU速度非常快的事实,在每次更改时重新计算:

_collection.ChangeTrackingEnabled = true;

Observable.Merge(
         _collection.Changed.Select(_ => Unit.Default), 
         _collection.ItemChanged.Select(_ => Unit.Default))
    .Select(_ => _collection.Sum(x => x.NumberToSum));

另一种方法对这样的聚合不是很好,但也非常有用,它将对列表中的每个项目执行一个块,并正确处理初始化、重置和移动。

StartWith
将解决您的问题。另外,我不确定您是否希望ItemChanged,它会在列表中的项目发生更改时发出信号,而不是在添加或删除项目时发出信号。在这里,您可能还想听听
Changed

虽然试图以这种方式保持“运行总数”很有诱惑力,但由于重置和移动,实际上很难做到这一点。更简单的方法是滥用CPU速度非常快的事实,在每次更改时重新计算:

_collection.ChangeTrackingEnabled = true;

Observable.Merge(
         _collection.Changed.Select(_ => Unit.Default), 
         _collection.ItemChanged.Select(_ => Unit.Default))
    .Select(_ => _collection.Sum(x => x.NumberToSum));

另一种方法对这样的聚合不是很好,但也非常有用,它将对列表中的每个项目执行一个块,并正确处理初始化、重置和移动。

感谢您提供的将ItemChanged与Change相结合的技巧。StartWith没有解决我的问题。或者我只是不知道如何正确使用它。你能举个例子吗?StartWith不是上面代码的唯一错误,但不包括它是CombineTest看起来“不起作用”的一个常见原因,因为在它对两个“方面”都有值之前,它不会为合并项随更改而更改的提示生成任何内容。StartWith没有解决我的问题。或者我只是不知道如何正确使用它。你能举个例子吗?StartWith不是上面代码的唯一错误,但不包括它是CombineTest看起来“不起作用”的一个常见原因,因为在它对两个“方面”都有值之前,它不会产生任何结果