Click here to Skip to main content
Click here to Skip to main content
Go to top

The best of reactive framework extensions

, 20 Feb 2014
Rate this:
Please Sign up or sign in to vote.
An enumeration of nice code rewrite of recurring spaghetti code thanks to Reactive Framework

Introduction  

Some of you may remember my love with Rx Framework began with a pet project I wrote about.
Now, I’m using Rx Framework almost every day, but this is thanks to a small little personal framework that made my life easier.

So, no big and complicated article today, it’s friday after all, just an enumeration of my best reactive framework extensions methods.  This article can be considered as the suite of this old one that grouped some of my utility classes.

Best of 

All methods I use such as .Subscribe will return a IDisposable that you can dispose if you want to unsubscribe. 

How to subscribe to PropertyChanged

When you are interested into a property that change on some of you view model, you often need to write the following spaghetti code :

public void UpdateUser(User user)
{
    user.PropertyChanged += user_PropertyChanged;
    NameChanged();
}
void user_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if(e.PropertyName == "Name")
        NameChanged();
}
private void NameChanged()
{
    //Do wonderfull stuff
} 

I replaced with 

user
    .ItemPropertyChanged(u=>u.Name,true)
    .Subscribe((args) =>
    {
        //Do wonderfull stuff with args.NewValue and args.OldValue
    });

The boolean fire the subscribe action directly a first time when you subscribe. Note that you can get the NewValue and OldValue of your property with the args argument, and do not have magic string anymore.

How to subscribe to CollectionChanged

Replace the old way of doing something on each items added to an observable collection :

public void SubscribeToCollection(ObservableCollection<User> users)
{
    users.CollectionChanged += users_CollectionChanged;
    foreach(var user in users)
    {
        NewUser(user);
    }
}
void users_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    if(e.NewItems != null)
        foreach(User user in e.NewItems)
        {
            NewUser(user);
        }
}
private void NewUser(User user)
{
    //Do something
}

Into the reactive way:

users
    .ForeachItem()
    .Subscribe(user =>
    {
        //Do something
    });

How to subscribe to items in a ObservableCollection

Well basically a spaghetti code combining the two previous old approach. I replaced the following spaghetti.

public void SubscribeToCollection(ObservableCollection<User> users)
{
    users.CollectionChanged += users_CollectionChanged;
    foreach(var user in users)
    {
        NewUser(user);
    }
}
void users_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    if(e.NewItems != null)
        foreach(User user in e.NewItems)
        {
            NewUser(user);
        }
    if(e.OldItems != null)
    {
        foreach(User user in e.OldItems)
        {
            user.PropertyChanged -= UserChanged;
        }
    }
}
private void NewUser(User user)
{
    user.PropertyChanged += UserChanged;
}
void UserChanged(object sender, PropertyChangedEventArgs e)
{
    //Do wonderfull stuff when one user changes
}

Into the clean version

users
    .ObserveEachItem(u => u.ItemPropertyChanged())
    .Subscribe(args =>
    {
        User user = args.Sender;
        //Do wonderfull stuff when one user changes
    });

Weak event listener

Have you tried to subscribe to an object weakly, so the garbage collector correctly garbage a listener that is no longer referenced anywhere ? Well, one solution is to read this msdn page and use the WeakEventManager. Sorry, I’m too lazy to read it for you.

The other solution is to use my ObserveWeakly method :

var subscription = user.ItemPropertyChanged()
                    .ObserveWeakly()
                    .Subscribe(args =>
                    {
                        User u = args.Sender;
                        //User changed do what you want...
                    });
subscription = null; //OMG forgot to Dispose the subscription !!! memory leak !1!
GC.Collect();
user.AssertSubscribers(0); //Just kidding 

Subscribe to dependency property changes

The code to subscribe to dependency properties is not trivial as you can see in the following snippet.

TextBox box = new TextBox();
DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(TextBox.BackgroundProperty, typeof(TextBox));
if(dpd != null)
{
    dpd.AddValueChanged(box, (sender, args) =>
    {
        //Do wonderfull stuff when the background changed
    });
}

But fear not, now you can do that.

TextBox box = new TextBox();
box.DependencyPropertyChanged<Brush>(TextBox.BackgroundProperty)
    .Subscribe(args =>
    {
        Brush brush = args.NewValue;
    });

Synchronize two ObservableCollection

I’m sure it happened to you more than once, for example you want an ObservableCollection<String> that list dynamically all the girls’ name of your ObservableCollection<User>. Here is the old way :

ObservableCollection<String> GirlsNames = new ObservableCollection<String>();
public void SubscribeToCollection(ObservableCollection<User> users)
{
    users.CollectionChanged += users_CollectionChanged;
    foreach(var user in users)
    {
        NewUser(user);
    }
}


void users_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    if(e.NewItems != null)
        foreach(User user in e.NewItems)
        {
            NewUser(user);
        }
    if(e.OldItems != null)
    {
        foreach(User user in e.OldItems)
        {
            GirlsNames.Remove(user.Name);
        }
    }
}
private void NewUser(User user)
{
    if(user.Gender = Gender.Girl)
        GirlsNames.Add(user.Name);
}

Now you can turn this spaghetti into a single line: (Always returns a IDisposable if you want to stop the mapping)

users.MapToCollection(GirlsNames, u=>u.Name, u=> u.Gender == Gender.Girl);

Conclusion

I put the sources and binaries as this article, I also have a private GIT repository and internal Nuget feed to deploy my framework in my own projects. I intend to switch to public GIT repository and public nuget feed, if you beg me. Wink | ;)

Anyway the solution ships with full unit tests for everything, feel free to play with it, if there is more that what you need don’t hesitate to just copy/paste my code if you don’t want all.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)

Share

About the Author

Nicolas Dorier
Software Developer Freelance
France France
I am a trainer and a curious developer.
 
CEO of AO-IS, we created a tool to make IaaS on Azure more easy IaaS Management Studio.
 
If you are interested for working with me, for fun coding stuff, for freelance stuff, or interested in using our cloud training infrastructure freely for a kickass presentation for the dev community ? this way Smile | :)

Comments and Discussions

 
QuestionQuestion regarding your ObserveEachItem extension PinmvpSacha Barber12-Mar-14 0:09 
AnswerRe: Question regarding your ObserveEachItem extension PinprofessionalNicolas Dorier12-Mar-14 2:11 
GeneralRe: Question regarding your ObserveEachItem extension [modified] PinmvpSacha Barber12-Mar-14 2:43 
GeneralRe: Question regarding your ObserveEachItem extension PinmvpSacha Barber9-May-14 1:24 
GeneralRe: Question regarding your ObserveEachItem extension PinprofessionalNicolas Dorier9-May-14 1:35 
GeneralRe: Question regarding your ObserveEachItem extension PinmvpSacha Barber9-May-14 22:06 
GeneralRe: Question regarding your ObserveEachItem extension PinprofessionalNicolas Dorier10-May-14 0:27 
GeneralRe: Question regarding your ObserveEachItem extension PinmvpSacha Barber10-May-14 3:06 
GeneralRe: Question regarding your ObserveEachItem extension PinprofessionalNicolas Dorier10-May-14 3:43 
GeneralRe: Question regarding your ObserveEachItem extension PinmvpSacha Barber10-May-14 7:10 
GeneralRe: Question regarding your ObserveEachItem extension PinmvpSacha Barber10-May-14 7:21 
GeneralRe: Question regarding your ObserveEachItem extension [modified] PinprofessionalNicolas Dorier10-May-14 9:36 
GeneralMy vote of 5 PinmemberJoachim_797172025-Feb-14 1:48 
GeneralRe: My vote of 5 PinprofessionalNicolas Dorier25-Feb-14 2:17 
QuestionFor us older coders: PinmemberJerry W. Manweiler, Ph.D.24-Feb-14 8:08 
AnswerRe: For us older coders: PinprofessionalNicolas Dorier24-Feb-14 8:43 
GeneralRe: For us older coders: PinmemberJerry W. Manweiler, Ph.D.24-Feb-14 9:36 
GeneralRe: For us older coders: PinprofessionalNicolas Dorier24-Feb-14 11:15 
QuestionMy vote of -1 PinprofessionalPaulo Zemek23-Feb-14 15:35 
AnswerRe: My vote of -1 PinprofessionalNicolas Dorier24-Feb-14 0:08 
QuestionI use Rx a lot in my code PinmvpSacha Barber21-Feb-14 0:38 
AnswerRe: I use Rx a lot in my code PinprofessionalNicolas Dorier21-Feb-14 1:50 
AnswerRe: I use Rx a lot in my code PinprofessionalNicolas Dorier24-Feb-14 0:10 
GeneralRe: I use Rx a lot in my code PinmvpSacha Barber6-Mar-14 6:22 
QuestionFine! +5! PinprofessionalVolynsky Alex20-Feb-14 23:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140921.1 | Last Updated 20 Feb 2014
Article Copyright 2014 by Nicolas Dorier
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid