When collection changed in ObservableCollection add new entries to ReactiveList

40 views
Skip to first unread message

Max Reble

unread,
Nov 9, 2017, 8:48:06 AM11/9/17
to ReactiveUI mailing list
Hi

I'm very new to ReactiveUI, and its quite hard for me to getting started. I have a ObservableCollection which getting filled from a TCP Model. When new data arrives, I want to create new Buttons inside an ItemsControl. It works the old way (with CollectionChanged) but I don't get it work with ReactiveUI. 

Could you may help me, by sending me to the right functions in reactiveUI or maybe by providing some sample code, I would be very pleased! 

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


public string UrlPathSegment => "ChooseMachine";

public IScreenTransportable HostScreen { get; }
IScreen IRoutableViewModel.HostScreen => HostScreen;

public ChooseMachineViewModel(IScreenTransportable screen)
{
HostScreen = screen;


//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
HostScreen.Transporter.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);
}
}
}


Thanks in advance,
Max

Valdimar Kristjánsson

unread,
Nov 9, 2017, 10:09:38 AM11/9/17
to ReactiveUI mailing list
Hi Max,

How about something like this?

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

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

And a test:

    [TestClass]
    public class ChooseMachineViewModelTest
    {
        [TestMethod]
        public void TestAddingAndRemovingFromSource()
        {
            var source = new ObservableCollection<CUStatus>();
            var model = new ChooseMachineViewModel(source);
            Assert.AreEqual(source.Count, model.ButtonList.Count);
            source.Add(new CUStatus(65034));
            Assert.AreEqual(source.Count, model.ButtonList.Count);
            source.Clear();
            Assert.AreEqual(source.Count, model.ButtonList.Count);
            source.Add(new CUStatus(65034));
            Assert.AreEqual(source.Count, model.ButtonList.Count);
            source.Add(new CUStatus(65034));//insert a duplicate
            Assert.AreEqual(source.Count-1, model.ButtonList.Count);
            Assert.AreEqual(source.Count - 1, model.ButtonList.Count);
        }
    }

Cheers,
nisbus

Valdimar Kristjánsson

unread,
Nov 9, 2017, 10:14:05 AM11/9/17
to ReactiveUI mailing list
please remove the addressToButton thingy :)

Max Reble

unread,
Nov 9, 2017, 10:44:10 AM11/9/17
to ReactiveUI mailing list
Just... Wow... Okay I definitely have to stick to ReactiveUI, this is just beautiful and easy to understand. For me its like Spanish: I can listen very good to some one who is speaking Spanish, but talking is quite hard for me ;-) 

Thank you very much Valdimar!
Reply all
Reply to author
Forward
0 new messages