当 ObservableCollection 中的集合发生变化时,将新条目添加到 ReactiveList

When collection changed in ObservableCollection add new entries to ReactiveList

我有一个 ObservableCollectionTcpClient 中填充。当新数据到达时(添加了新项目),我想在 ItemsControl 内创建新按钮。它以旧方式工作(使用 CollectionChanged),但我无法使用 ReactiveUI

我是 ReactiveUI 的新手,对我来说很难入门。您能否帮助我走上正确的道路或者提供一些示例代码?

想法:

public class ChooseMachineViewModel : ReactiveObject
{
    public ReactiveList<Button> ButtonList { get; set; }
    private Dictionary<ushort, Button> addressToButton;

    //This one is normaly in another class and will be filled by a TcpClient
    public readonly ObservableCollection<WWSS.Message.CUStatus> ControlUnitsStatus;

    public ChooseMachineViewModel()
    {



        //TODO: Make this Reactive!
        //The ButtonList for an ItemsControl
        ButtonList = new ReactiveList<Button>();
        //The Dictonary for addresses -> Button
        addressToButton = new Dictionary<ushort, Button>();
        //The ObservableCollection filled by a TCP Server
        ControlUnitsStatus.CollectionChanged += ControlUnitsStatus_CollectionChanged;

    }


    private void ControlUnitsStatus_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {

        if (e.NewItems != null)
        {
            foreach (WWSS.Message.CUStatus stat in e.NewItems)
            {
                TryAddButton(stat);//When new Status arrive, try to create new button
            }
        }
        if (e.OldItems != null)
        {
            foreach (WWSS.Message.CUStatus stat in e.OldItems)
            {
                TryRemoveButton(stat);//When Status removed, try to remove the button
            }
        }
    }

    private bool TryAddButton(WWSS.Message.CUStatus status)
    {
        if (!addressToButton.ContainsKey(status.Address))//if the Address is already in the dictonary don't create a button
        {
            var but = new Button { Content = status.Address.ToString() };
            addressToButton.Add(status.Address, but);
            ButtonList.Add(but);
            return true;
        }
        return false;
    }
    private void TryRemoveButton(WWSS.Message.CUStatus status)
    {
        if (addressToButton.ContainsKey(status.Address))
        {
            ButtonList.Remove(addressToButton[status.Address]);
            addressToButton.Remove(status.Address);

        }
    }
}

诀窍是使用 CreateDerivedCollection:

public class ChooseMachineViewModel : ReactiveObject
{
    public IReactiveDerivedList<Button> ButtonList { get; set; }

    public ChooseMachineViewModel(ObservableCollection<CUStatus> source)
    {
        addressToButton = new Dictionary<ushort, Button>();
        ButtonList = ControlUnitsStatus.CreateDerivedCollection(status => new Button { Content = status.Address.ToString() },
                                                    status => !ButtonList.Any(button => button.Content.ToString().Equals(status.Address.ToString())));
    }
}