如何在 ReactiveUI 中通过单击按钮设置 TextBox 值

How to set a TextBox value with a button click in ReactiveUI

我正在尝试掌握 ReaxtiveX/ReaxtiveUI 并试图制作一个非常简单的程序;一个文本框、一个文本块和一个按钮。我希望 TextBox 有一个初始值,并且在 TextBox 中键入的任何内容都显示在 TextBlock 中。单击按钮时,TextBox 中的文本将更改,因此 TextBlock 中的文本也会更改。我让 TextBlock 更新得很好,但无法让按钮工作。

这是我的代码

MainWindowViewModel.cs:

public class MainWindowViewModel : ReactiveObject
{
    //private string _inputText;
    //public string InputText
    //{
    //    get => _inputText;
    //    set => this.RaiseAndSetIfChanged(ref _inputText, value);
    //}

    private ObservableAsPropertyHelper<string> _inputText;
    public string InputText => _inputText.Value;

    private ObservableAsPropertyHelper<string> _copyText;
    public string CopyText => _copyText.Value;

    public ReactiveCommand<Unit, string> ChangeInputText { get; }
        
    public MainWindowViewModel ()
    {
        //InputText = "Starting Text";
        _inputText = ChangeInputText.ToProperty(this, nameof(InputText), "Starting Text");

        _copyText = this
            .WhenAnyValue(x => x.InputText)
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Select(x => x.ToUpperInvariant())
            .DistinctUntilChanged()
            .WhereNotNull()
            .ObserveOn(RxApp.MainThreadScheduler)
            .ToProperty(this, x => x.CopyText);

            ChangeInputText = ReactiveCommand.Create<Unit, string>(_ => { return "Text Changed"; });
    }        
}

MainWindow.xaml.cs

public partial class MainWindow : ReactiveWindow<MainWindowViewModel>
{
    public MainWindow ()
    {
        InitializeComponent();
        ViewModel = new MainWindowViewModel();
    
        this.WhenActivated(d =>
        {
            this.Bind(ViewModel, vm => vm.InputText, v => v.testTextBox.Text).DisposeWith(d);

            this.OneWayBind(ViewModel, vm => vm.CopyText, v => v.copyTextBlock.Text).DisposeWith(d);

            this.BindCommand(ViewModel, vm => vm.ChangeInputText, v => v.changeButton).DisposeWith(d);
        });
    }
}

MainWindow.xaml

<Border Padding="5">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <TextBox x:Name="testTextBox"
                Grid.Row="0"
                Grid.Column="0"
                Grid.ColumnSpan="3" />
        <Button x:Name="changeButton"
                Grid.Row="1"
                Grid.Column="1"
                Margin="5"
                Content="Change Text" />
        <Border BorderThickness="1"
                BorderBrush="Black"
                Grid.Row="2"
                Grid.Column="0"
                Grid.ColumnSpan="3">
            <TextBlock x:Name="copyTextBlock" />
        </Border>
    </Grid>
</Border>

我从 InputText 作为 属性 开始,并在 ViewModel ctor 中设置初始值(在我尝试实现按钮命令之前)。它工作正常,TextBox 具有初始值,其内容反映在 TextBlock 中。当我尝试实现按钮命令时,我将 InputText 更改为 OAPH,因为据我所知,您不能使用 ToProperty().

的属性

现在,当我 运行 项目时,我得到了这个

我做错了什么?

编辑:

这是 Glenn Watson 帮助我后的工作 ViewModel。

public class MainWindowViewModel : ReactiveObject
{
    //Made Imput text a property instead of an OAPH
    private string _inputText;
    public string InputText
    {
        get => _inputText;
        set => this.RaiseAndSetIfChanged(ref _inputText, value);
    }

    private readonly ObservableAsPropertyHelper<string> _copyText;
    public string CopyText => _copyText.Value;

    public ReactiveCommand<Unit, string> ChangeInputText { get; }

    public MainWindowViewModel ()
    {
        InputText = "Starting Text";
        ChangeInputText = ReactiveCommand.Create<Unit, string>(_ => { return "Text Changed"; });//.BindTo(this, x => x.InputText);
        ChangeInputText.BindTo(this, x => x.InputText); //Added BindTo

    _copyText = this
        .WhenAnyValue(x => x.InputText)
        .ObserveOn(RxApp.TaskpoolScheduler)
        .Select(x => x.ToUpperInvariant())
        .DistinctUntilChanged()
        .WhereNotNull()
        .ObserveOn(RxApp.MainThreadScheduler)
        .ToProperty(this, x => x.CopyText);  
    }        
}

ChangeInputText 在您 ToProperty() 时 RxCommand 尚未创建。将它移到您的 ReactiveCommand.Create( 调用下方。