Quick introduction to Righthand.SharpRedux library

I've been experimenting with a redux implementation for .net lately and here is the current state.

The core library is quite functional and ready for a bit more serious test drive. There is also a visualizer, redux based, and with a frontend for WPF (other frontends can be added).

Available are two sample apps, Todo which is a WPF/MVVM/redux implementation of TodoMVC. And a dirty Playground sample.

Here are two screenshots from Todo sample and a brief introduction:

The application itself is on the left while visualizer is on the right. Visualizer is further composed of actions list and state|difference display. Above it shows current state after highlighted action. Value "[0] 1" in visualizer means list item with index 0 (when a list member) and item has an unique key with value 1 (when applicable).

Above the visualizer is showing state difference between the last action and previous one. You can also select any action from the list and click Reset to State which would rewind the state to one after that action.

But why would anybody bother with redux at all? The answer is logging, separation, unit testing and state rewind. Imagine you have an application that crashes - getting all the actions in proper order would give you the ability to reply exactly what user/application was doing until it crashed - even without any user intervention or feedback.

That's it for a quick introduction. I'll try to blog more, create more documentation about it, based also on feedback/interest. I'll try using it in a real project when an occasion appears. Also visualizer can be and probably will be improved. Right now is something that works well enough for start.

Righthand.SharpRedux is open source and hosted on github and libraries will appear soon on NuGet. You can also get the Todo sample as a zip (.net 4.6.2 required),

Immutable types are based on Righthand.Immutable which is also hosted on NuGet. Visual Studio 2017 extension that creates immutable code is available at Marketplace. Righthand.Immutable is optional for SharpRedux and can be used standalone.

DevExpress’ FlowLayoutControl and MVVM

FlowLayoutControl unfortunately doesn’t support items binding. You can’t just provide a source and hope FlowLayoutControl will populate the content. But fear not, there is nothing attached properties can’t solve.

I’ve created an attached property ItemsSource that does all that for you. Here is its declaration:

public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.RegisterAttached("ItemsSource", typeof(IEnumerable), typeof(FlowLayoutExtensions), 
            new UIPropertyMetadata(null, new PropertyChangedCallback(OnItemsSourceChanged)));

It accepts an IEnumerable as an input.

And here is the relevant code when ItemsSource changes:

private static void OnItemsSourceChanged(DependencyObject o, IEnumerable oldValue, IEnumerable newValue)
{    
    FlowLayoutControl layout = o as FlowLayoutControl;
    if (layout != null)
    {

        NotifyCollectionChangedEventHandler collectionChanged = delegate(object s, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    AddItems(layout, e.NewItems);
                    break;
                case NotifyCollectionChangedAction.Remove:
                    RemoveItems(layout, e.OldItems);
                    break;
            }
        };

        // remove event implementation
        if (oldValue != null)
        {
            INotifyCollectionChanged oldIncc = oldValue as INotifyCollectionChanged;
            if (oldIncc != null)
                oldIncc.CollectionChanged -= collectionChanged;
        }
        layout.Children.Clear();

        if (newValue != null)
        {
            AddItems(layout, newValue);
            INotifyCollectionChanged incc = newValue as INotifyCollectionChanged;
            if (incc != null)
            {
                incc.CollectionChanged += collectionChanged;
            }
        }
    }
}

First it defines a delegate that gets called upon collection changes (when source is INotifyCollectionChanged) then it unsubscribes from CollectionChanged if it has previously subscribed. And finally it populates FlowLayoutControl with items and optionally subscribes to CollectionChanged event (when source supports it). Note that ObservableCollection<T> implements INotifyCollectionChanged.

Here is the code that adds or removes items:

private static void AddItems(FlowLayoutControl layout, IEnumerable source)
{
    foreach (object item in source)
    {
        GroupBox box = new GroupBox { DataContext = item };
        layout.Children.Add(box);
    }
}

private static void RemoveItems(FlowLayoutControl layout, IEnumerable source)
{
    foreach (object item in source)
    {
        GroupBox match = (from gb in layout.Children.OfType<GroupBox>()
                          where gb.DataContext == item
                          select gb).FirstOrDefault();
        if (match != null)
            layout.Children.Remove(match);
    }
}

Add items adds an GroupBox instance for each new item and sets its DataContext to the item. While RemoveItems searches for a matching GroupBox (based on DataContext match) instance and removes it from the FlowLayoutControl's Children collection.

A bit of XAML is required as well. I control the GroupBox appearance through a Style, like this:

<Style TargetType="dxlc:GroupBox">
    <Setter Property="MaximizeElementVisibility" Value="Visible"/>
    <Setter Property="MinimizeElementVisibility" Value="Visible"/>
    <Setter Property="Width" Value="150"/>
    <Setter Property="Header" Value="{Binding Caption}" />
    <Setter Property="Content" Value="{Binding}" />
</Style>

Note the binding of the Content property (remember, I am assigning current item as DataContext). And here is the FlowLayoutControl instance declaration:

<dxlc:FlowLayoutControl loc:FlowLayoutExtensions.ItemsSource="{Binding}" />

There you go, a MVVM friendly approach.

Note that this is not a fully featured code but it is a good starting point.

31.8.2011 - correct demo files

20.9.2011 - ufff, again uploaded really proper demo

FlowLayoutExtensionsDemo.zip (9.99 kb)