user3239780
user3239780

Reputation: 35

ReactiveUI binding with dependencyproperty and pass to viewmodel

I started using ReactiveUI (with WPF) for first time and have little problem which I couldn't google out or find on docs. How do you bind properties from Control's DependencyProperty?

I'm creating a user control

public partial class MotorControlView: ReactiveUserControl<MotorControlViewModel>

and inside the class I have dependency property MotorAxis

public static readonly DependencyProperty MotorAxisProperty = DependencyProperty.Register(
    "MotorAxis", typeof(MotorAxis), typeof(MotorControlView));

public MotorAxis MotorAxis
{
    get => (MotorAxis) GetValue(MotorAxisProperty);
    set => SetValue(MotorAxisProperty, value);
}

Inside the view there is TextBlock which should show MotorAxis (it's an enum) string value (NoVal/X/Y/Z). The property is set in MainWindow.XAML ( <uc:MotorControlView MotorAxis="Y" /> )

The problem is:

In the constructor its value is always default (NoVal), so I think I can't pass it to viewmodel constuctor...

The ViewModel will be responsible for accessing X/Y/Z motor based on this parameter


The only solution I got found out is doing so:

//In View:
public MotorControlView()
{
    InitializeComponent();
    ViewModel = new MotorControlViewModel();
    this.WhenActivated(dr =>
    {
        ViewModel.MotorAxis = this.MotorAxis;
    });
    this.Bind(ViewModel, vm => vm.MotorAxis, v => v.MotorAxisBlock.Text);
}

//In VM: property with this.RaiseAndSetIfChanged(ref this.motorAxis, value)

Is there a more elegant way to do this without manually setting value in WhenActivated? So I will have this value accessible in eg. VM's constructor?

Upvotes: 2

Views: 1836

Answers (1)

Glenn Watson
Glenn Watson

Reputation: 2888

Reactiveui uses code behind bindings.

Typically you would place these in the constructor.

Main advantage of the reactiveui way is type safety.

public MotorControlView
{
  this.Bind(this.ViewModel, viewModel => viewModel.Axis, view => view.MotorControl.Text, axis => axis.ToString(), axisString => (MotorAxis)Enum.Parse(typeof(MotorAxis), axisString);
}

The above is doing Bind in the constructor. The following parameters are passed:

  1. The view model
  2. A expression pointing towards the property on the view model
  3. A expression pointing towards the property on the view
  4. A converter method taking the property on the view model, converting to a string and putting that on the view
  5. A converter method taking the string on the view and converting to the enum on the view model.

See https://reactiveui.net/docs/handbook/data-binding/ for further info.

Upvotes: 2

Related Questions