0

Suppose I have a WPF two-way data binding between a source (CLR property) and a destination (UI control property). Now anytime the destination property is updated, I want to update the source property on a non-UI thread (not on Dispatcher thread). In my application, I am using Rx (Reactive Extension) Scheduler, thus, I plan to provide one Rx scheduler for the execution.

As an example, if I bind the property Value of the following object and the UI updates the property using the binding, I want the setter of Value property to be executed on an Rx scheduler I provided.

public class A : VMBase {  // VMBase provides the plumbing of INotifyPropertyChanged
    private string _Value;
    public string Value {
        get { return _Value; }
        set { SetField(ref _Value, value, () => Value); }
    }
}

It is possible to modify the source property's setter to switch the update to another thread.

public class A : VMBase {  // VMBase provides the plumbing of INotifyPropertyChanged
    private string _Value;
    public string Value {
        get { return _Value; }
        set { GetScheduler().Schedule(() => SetField(ref _Value, value, () => Value)); }
    }
}

However, in my case this is not practical because I need to ask my users to modify their codes.

Googling the issue, I found that I can create a custom WPF binding as follows: http://www.hardcodet.net/2008/04/wpf-custom-binding-class. However, I couldn't find where I should hook the code to invoke the update on the Rx scheduler.

Any solutions or hint ? I am also opened to solutions based on Reactive Extensions or Reactive UI.

Thanks.

nikoniko
  • 833
  • 2
  • 11
  • 22
  • could you please share some info of what you are trying to do? The UI will always execute on the UI thread so will the binding. I'm just not clear what you mean with "Executing on a background thread". The object is just there is not bound to a thread.... – Martin Moser Apr 07 '15 at 06:48
  • Hi, thanks for the comment. I updated my question above. Hope it makes it clearer what I want to achieve. You may wonder why I want to switch the thread. It's because in my application I need to access all my View Model classes on a specific thread (!= UI thread). – nikoniko Apr 07 '15 at 07:34
  • What version of the framework are you using? Because after 4 INPC events fired on non-ui threads are automatically marshalled onto the UI thread by Bindings. –  Apr 07 '15 at 14:35
  • I am using .NET 4.0. Yes, I am aware that INPC events fired on non-ui threads are automatically marshalled onto the UI thread. – nikoniko Apr 08 '15 at 04:02

1 Answers1

0

It can introduce quite a bit more work, but you can use interactions to link Commands in your ViewModel to Events on your controls. This should allow you to intercept the event causing the value update on your ViewModel and set your Value property using whatever method you like. Here I've also used the MVVM Light framework's 'EventToCommand', but you can swap in <i:InvokeCommandAction... if you're using something else.

<UserControl 
...other namespaces, declarations, etc...
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">

    <Grid>
        <Button>
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <cmdextras:EventToCommand Command="{Binding Path=SomethingWentClickCommand}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
    </Grid>

</UserControl>

Reconfigure this to suit whatever control/event you're using, then your codebehind/viewmodel class needs a RelayCommand called SomethingWentClickCommand to retrieve the new value and update your binding property accordingly.

goobering
  • 1,547
  • 2
  • 10
  • 24
  • Hi. I just want to bind CLR properties to my View and intercept the call to the property setters. It's not practical in my case to create Commands in between for the interception. Anyway thanks. – nikoniko Apr 08 '15 at 04:02