[RxUI] 3.5 – Windows Presentation Foundation(WPF)

[RxUI] 3.5 – Windows Presentation Foundation(WPF)

手动实现IViewFor<T>,并确保ViewModel是DependencyProperty。另外,应始终通过WhenActivated取消绑定,否则会导致内存泄漏。如果不使用WhenActivated,那么XAML的DependencyProperty系统会导致内存泄漏。有几条规则需要注意,最重要的一条是:如果对除此之外的其它任何操作执行WhenAny,则需要将其放在WhenActivated中。有关详细信息,请参见WhenActivated

本示例中的目标是将ViewModel的TheText属性双向绑定到TextBox,并将TheText属性单向绑定到TextBlock,因此当用户在TextBox中键入文本时,TextBlock就会更新。

public class TheViewModel : ReactiveObject
{
    private string theText;
    public string TheText
    {
        get => theText;
        set => this.RaiseAndSetIfChanged(ref this.theText, value);
    }

    public ReactiveCommand<Unit,Unit> TheTextCommand { get; }

    public TheViewModel()
    {
        TheTextCommand = ReactiveCommand
            .CreateFromObservable(ExecuteTextCommand);
    }

    private IObservable<Unit> ExecuteTextCommand()
    {
        TheText = "Hello ReactiveUI";
        return Observable.Return(Unit.Default);
    }
}
<Window /* snip */>
  <StackPanel>
    <TextBox x:Name="TheTextBox" />
    <TextBlock x:Name="TheTextBlock" />
    <Button x:Name="TheTextButton" />
  </StackPanel>
</Window>

在此示例中,将手动实现IViewFor<TViewModel>接口,但对于UserControl,应该使用封装了IViewFor实现的ReactiveUserControl

public partial class TheView : Window, IViewFor<TheViewModel>
{
    public static readonly DependencyProperty ViewModelProperty = DependencyProperty
        .Register(nameof(ViewModel), typeof(TheViewModel), typeof(TheView));

    public TheView()
    {
        InitializeComponent();
        ViewModel = new TheViewModel();

        // Setup the bindings
        // Note: We have to use WhenActivated here, since we need to dispose the
        // bindings on XAML-based platforms, or else the bindings leak memory.
        this.WhenActivated(disposable =>
        {
            this.Bind(this.ViewModel, x => x.TheText, x => x.TheTextBox.Text)
                .DisposeWith(disposable);
            this.OneWayBind(this.ViewModel, x => x.TheText, x => x.TheTextBlock.Text)
                .DisposeWith(disposable);
            this.BindCommand(ViewModel, x => x.TheTextCommand, x => x.TheTextButton)
                .DisposeWith(disposable);
        });
    }

    public TheViewModel ViewModel
    {
        get => (TheViewModel)GetValue(ViewModelProperty);
        set => SetValue(ViewModelProperty, value);
    }

    object IViewFor.ViewModel
    {
        get => ViewModel;
        set => ViewModel = (TheViewModel)value;
    }
}

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注