runceel / ReactiveProperty

ReactiveProperty provides MVVM and asynchronous support features under Reactive Extensions. Target frameworks are .NET 6+, .NET Framework 4.7.2 and .NET Standard 2.0.
MIT License
903 stars 101 forks source link

Throttle ReactiveCommand #4

Closed SolveSoul closed 9 years ago

SolveSoul commented 9 years ago

Hi

I'm not sure if this was the right place to post but I have a question. How can I throttle/sample/... a ReactiveCommand? I want to implement the typical autocomplete feature but I'm bound to a MVVM pattern. So what I need to do is make sure the KeyUp event (bound to a ReactiveCommand) only fires when the user is done typing (Throttle with a TimeSpan) so I can query an API.

I can't seem to find something similar in the samples, the WP8.1 sample shows how to delay a result to a ReactiveProperty but not a ReactiveCommand. Any ideas or am I doing this completely wrong?

Thanks for your help!

runceel commented 9 years ago

Thank you for your question!

I can't speak english well.I'm sorry if you have misread your question.

You can use EventToReactiveCommand class. It can delay fires events. I talk C# code :)

Write throttle converter.

using Reactive.Bindings.Interactivity;
using System;
using System.Reactive.Linq;

namespace WpfApplication8
{
    public class ThrottleReactiveConverter : ReactiveConverter<EventArgs, object>
    {
        protected override IObservable<object> OnConvert(IObservable<EventArgs> source)
        {
            return source
                .Throttle(TimeSpan.FromMilliseconds(500))
                .Select(_ => (object)null);
        }
    }
}

example VM

using Reactive.Bindings;
using System;
using System.Windows;

namespace WpfApplication8
{
    public class MainWindowViewModel
    {
        public ReactiveProperty<string> Text { get; private set; }

        public ReactiveCommand AutoCompleteStartCommand { get; private set; }

        public MainWindowViewModel()
        {
            this.Text = new ReactiveProperty<string>();
            this.AutoCompleteStartCommand = new ReactiveCommand();
            this.AutoCompleteStartCommand.Subscribe(_ =>
                {
                    MessageBox.Show(this.Text.Value);
                });
        }
    }
}

Binding!

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
    xmlns:Interactivity="clr-namespace:Reactive.Bindings.Interactivity;assembly=ReactiveProperty.NET45"
    xmlns:local="clr-namespace:WpfApplication8"
    x:Class="WpfApplication8.MainWindow"
    Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <StackPanel>
        <TextBox Text="{Binding Text.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="KeyUp">
                    <Interactivity:EventToReactiveCommand Command="{Binding AutoCompleteStartCommand}">
                        <local:ThrottleReactiveConverter />
                    </Interactivity:EventToReactiveCommand>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </TextBox>
    </StackPanel>
</Window>

This code is delay(500ms) binding to ReactiveCommand.

SolveSoul commented 9 years ago

Thanks a lot for the quick response. This was exactly what I needed!