Привязка ReactiveUI с зависимостью свойства и передача в viewmodel - PullRequest
1 голос
/ 23 января 2020

Я начал использовать ReactiveUI (с WPF) впервые и у меня возникла небольшая проблема, которую я не смог найти в Google или найти в документации. Как связать свойства из DependencyProperty элемента управления?

Я создаю пользовательский элемент управления

public partial class MotorControlView: ReactiveUserControl<MotorControlViewModel>

, а внутри класса у меня есть свойство зависимостей MotorAxis

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

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

Внутри представление там TextBlock, которое должно показывать MotorAxis (это перечисление) строковое значение (NoVal / X / Y / Z). Свойство установлено в MainWindow.XAML (<uc:MotorControlView MotorAxis="Y" />)

Проблема заключается в следующем:

  • как связать текст метки со свойством элемента управления MotorAxis с помощью ReactiveUI ?
  • как передать значение ViewModel

В конструкторе его значение всегда по умолчанию (NoVal), поэтому я думаю, что не могу передать его конструктору viewmodel ...

ViewModel будет отвечать за доступ к двигателю X / Y / Z на основе этого параметра


Единственное решение, которое я обнаружил, заключается в следующем:

//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);
}

// В VM: свойство с this.RaiseAndSetIfChanged(ref this.motorAxis, value)

Есть ли более элегантный способ сделать это без установки значения вручную в WhenActivation? Так что я буду иметь это значение, например, в. Конструктор ВМ?

Ответы [ 2 ]

1 голос
/ 23 января 2020

Reactiveui использует код за привязками.

Обычно вы помещаете их в конструктор.

Основным преимуществом способа реагирования является безопасность типов.

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

Выше приведено выполнение привязки в конструкторе. Передаются следующие параметры:

  1. Модель представления
  2. Выражение, указывающее на свойство в модели представления
  3. Выражение, указывающее на свойство в представлении
  4. Метод преобразователя, принимающий свойство в модели представления, преобразующий в строку и помещающий его в представление
  5. Метод преобразователя, принимающий строку в представлении и преобразующий в перечисление в модели представления ,

См. https://reactiveui.net/docs/handbook/data-binding/ для получения дополнительной информации.

0 голосов
/ 07 мая 2020

Я пробовал вот так, но по какой-то причине не работает:

ViewModel

using ReactiveUI;
using ReactiveUI.Fody.Helpers;

public sealed class MyViewModel : ReactiveObject
{
    [Reactive]
    public string Text { get; set; } = string.Empty;
}

Control

public partial class MyControl: UserControl, IViewFor<MyViewModel>
{
    // register property in the dependency property tracker
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register(nameof(Text), typeof(string), typeof(MyControl));

    // get/set value from/to dependency property tracker
    public string Text
    {
        get => (string)GetValue(TextProperty);
        set => SetValue(TextProperty, value);
    }

    public MyControl()
    {
        InitializeComponent();

        this.WhenActivated(d =>
        {
            // Note: always dispose bindings with composite disposable
            // Note: use overloads for value conversion or one-way-binding as needed
            this.Bind(ViewModel, vm => vm.Text, v => v.Text).DisposeWith(d);
        });
    }

    #region IViewFor
    object IViewFor.ViewModel
    {
        get => ViewModel;
        set => ViewModel = value as MyViewModel;
    }

    public MyViewModel ViewModel
    {
        get => DataContext as MyViewModel;
        set => DataContext = value;
    }
    #endregion
}
...