更新绑定到由同一局部变量支持的属性的文本框
Update TextBoxes bound to properties backed by the same local variable
在使用 ReactiveUI 的应用程序中,我有两个属性由同一个局部变量支持。然后使用属性绑定到两个文本框,其中一个显示值,另一个显示值乘以 2。我需要让一个框反映另一个框中的更改。
视图模型:
public class AppViewModel : ReactiveObject
{
private int? _boxCommon;
public int? boxOrg
{
get => _boxCommon;
set
{
Trace.WriteLine($"**** Check1: {value}");
_ = this.RaiseAndSetIfChanged(ref _boxCommon, value);
}
}
public int? boxDouble
{
get => _boxCommon * 2;
set
{
Trace.WriteLine($"**** Check2: {value}");
_ = this.RaiseAndSetIfChanged(ref _boxCommon, (int)value / 2);
}
}
private int? lastVal;
public AppViewModel()
{
_boxCommon = 10;
lastVal = 10;
// Reflect changes to the other box.
this.WhenAnyValue(x => x.boxOrg)
.Throttle(TimeSpan.FromMilliseconds(800))
.Select((t) =>
{
if (t != lastVal)
{
return t * 2;
}
else
{
return boxDouble;
}
})
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe((t) => boxDouble = t); // seems reduntdant cause both backed by the same var.
this.WhenAnyValue(x => x.boxDouble)
.Throttle(TimeSpan.FromMilliseconds(800))
.Select((t) =>
{
if (t != lastVal)
{
return t / 2;
}
else
{
return boxOrg;
}
})
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe((t) => boxOrg = t);
}
}
查看:
<reactiveui:ReactiveWindow
x:Class="ReactiveDemo.MainWindow"
x:TypeArguments="reactivedemo:AppViewModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:reactivedemo="clr-namespace:ReactiveDemo"
xmlns:reactiveui="http://reactiveui.net"
Title="Test" Height="150" Width="200"
mc:Ignorable="d">
<Grid Margin="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="OrgNum: "/>
<TextBox Grid.Column="1" x:Name="orgBox" />
<TextBlock Grid.Row="1" Text="DoubleNum: "/>
<TextBox Grid.Column="1" Grid.Row="1" x:Name="doubleBox" />
</Grid>
</reactiveui:ReactiveWindow>
查看后面的代码:
public MainWindow()
{
InitializeComponent();
ViewModel = new AppViewModel();
this.WhenActivated(disposableRegistration =>
{
// Notice we don't have to provide a converter, on WPF a global converter is
// registered which knows how to convert a boolean into visibility.
this.Bind(ViewModel,
viewModel => viewModel.boxOrg,
view => view.orgBox.Text)
.DisposeWith(disposableRegistration);
this.Bind(ViewModel,
viewModel => viewModel.boxDouble,
view => view.doubleBox.Text)
.DisposeWith(disposableRegistration);
});
}
当我在一个框中进行更改时,Trace 会打印出设置到另一个框中的新值。但是,GUI 元素不会更新为新值。 WPF 和 ReactiveUI 的新手,非常感谢任何指点。
您宁愿使用 ValueConverter 而不是您的解决方案:
视图模型:
private int _boxSingle;
public int BoxSingle
{
get => _boxSingle;
set
{
this.RaiseAndSetIfChanged(ref _boxSingle, value);
}
}
绑定:
this.Bind(ViewModel, vm => vm.BoxSingle, view => view.textBox1.Text)
.DisposeWith(d);
this.Bind(ViewModel, vm => vm.BoxSingle, view => view.textBox2.Text,
v => (v * 2).ToString(),
v => int.Parse(v) / 2 )
.DisposeWith(d);
在使用 ReactiveUI 的应用程序中,我有两个属性由同一个局部变量支持。然后使用属性绑定到两个文本框,其中一个显示值,另一个显示值乘以 2。我需要让一个框反映另一个框中的更改。
视图模型:
public class AppViewModel : ReactiveObject
{
private int? _boxCommon;
public int? boxOrg
{
get => _boxCommon;
set
{
Trace.WriteLine($"**** Check1: {value}");
_ = this.RaiseAndSetIfChanged(ref _boxCommon, value);
}
}
public int? boxDouble
{
get => _boxCommon * 2;
set
{
Trace.WriteLine($"**** Check2: {value}");
_ = this.RaiseAndSetIfChanged(ref _boxCommon, (int)value / 2);
}
}
private int? lastVal;
public AppViewModel()
{
_boxCommon = 10;
lastVal = 10;
// Reflect changes to the other box.
this.WhenAnyValue(x => x.boxOrg)
.Throttle(TimeSpan.FromMilliseconds(800))
.Select((t) =>
{
if (t != lastVal)
{
return t * 2;
}
else
{
return boxDouble;
}
})
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe((t) => boxDouble = t); // seems reduntdant cause both backed by the same var.
this.WhenAnyValue(x => x.boxDouble)
.Throttle(TimeSpan.FromMilliseconds(800))
.Select((t) =>
{
if (t != lastVal)
{
return t / 2;
}
else
{
return boxOrg;
}
})
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe((t) => boxOrg = t);
}
}
查看:
<reactiveui:ReactiveWindow
x:Class="ReactiveDemo.MainWindow"
x:TypeArguments="reactivedemo:AppViewModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:reactivedemo="clr-namespace:ReactiveDemo"
xmlns:reactiveui="http://reactiveui.net"
Title="Test" Height="150" Width="200"
mc:Ignorable="d">
<Grid Margin="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="OrgNum: "/>
<TextBox Grid.Column="1" x:Name="orgBox" />
<TextBlock Grid.Row="1" Text="DoubleNum: "/>
<TextBox Grid.Column="1" Grid.Row="1" x:Name="doubleBox" />
</Grid>
</reactiveui:ReactiveWindow>
查看后面的代码:
public MainWindow()
{
InitializeComponent();
ViewModel = new AppViewModel();
this.WhenActivated(disposableRegistration =>
{
// Notice we don't have to provide a converter, on WPF a global converter is
// registered which knows how to convert a boolean into visibility.
this.Bind(ViewModel,
viewModel => viewModel.boxOrg,
view => view.orgBox.Text)
.DisposeWith(disposableRegistration);
this.Bind(ViewModel,
viewModel => viewModel.boxDouble,
view => view.doubleBox.Text)
.DisposeWith(disposableRegistration);
});
}
当我在一个框中进行更改时,Trace 会打印出设置到另一个框中的新值。但是,GUI 元素不会更新为新值。 WPF 和 ReactiveUI 的新手,非常感谢任何指点。
您宁愿使用 ValueConverter 而不是您的解决方案:
视图模型:
private int _boxSingle;
public int BoxSingle
{
get => _boxSingle;
set
{
this.RaiseAndSetIfChanged(ref _boxSingle, value);
}
}
绑定:
this.Bind(ViewModel, vm => vm.BoxSingle, view => view.textBox1.Text)
.DisposeWith(d);
this.Bind(ViewModel, vm => vm.BoxSingle, view => view.textBox2.Text,
v => (v * 2).ToString(),
v => int.Parse(v) / 2 )
.DisposeWith(d);