S.N
S.N

Reputation: 5140

WPF Combo and Rx FromEvent Pattern

I am in process of developing a WPF app to practice Rx with MVVM.

Scenario

I have a View (MVVM) with a combo (some company name) and a detail (company journal) section; I wanted to populate detail section when user select an item from combo box.

The detail section data is populated with the help of a WCF service method, which take company name as input and Task<> as output.

Problem

Users sometime select combo box items in quick succession, which leads my window to freeze. I presume, this might be because of event queue up Or due to slow result from wcf service method.

Therefore, I am thinking to use Rx's FromEvent pattern (MVVM fashion), which shall be able to observe ComboBox SelectedItem Change event to load data from wcf and skip events those are coming in quick succession using some throttle.

I appreciate any sample implementations while respecting MVVM.

Upvotes: 1

Views: 604

Answers (1)

MojoFilter
MojoFilter

Reputation: 12276

I think that the operator you are looking for is Switch(). I couldn't find an msdn page for it, but this is the signature you're after:

public static IObservable<TSource> Switch<TSource>(this IObservable<Task<TSource>> sources)

That will take an IObservable<Task<T>> and turn it into an IObservable<T> which produces the results of the most recent Task<T> received.

Here is an example implementation that doesn't use any MVVM, but I'm sure you can see how it would apply:

MainWindow.xaml

<Window x:Class="LastFromCombo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <ComboBox Name="cbx" />
            <TextBlock Name="result" />
        </StackPanel>
    </Grid>
</Window>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.cbx.ItemsSource = Enumerable.Range(0, 100);

        Observable.FromEventPattern<SelectionChangedEventArgs>(this.cbx, "SelectionChanged")
            .Select(ev => ev.EventArgs.AddedItems.Cast<object>().FirstOrDefault())
            .Select(GetDetails)
            .Switch()
            .ObserveOnDispatcher()
            .Subscribe(detail => this.result.Text = detail);
    }

    private static async Task<string> GetDetails(object data)
    {
        await Task.Delay(TimeSpan.FromSeconds(3.0));
        return "Details from " + data;
    }
}

Upvotes: 3

Related Questions