行为主题为WPF ViewModel支持字段 [英] Behaviour Subject as WPF ViewModel backing field
问题描述
我一直在阅读Lee Campbell对rx的介绍,它对于加快框架的使用非常有帮助。
I've been reading Lee Campbell's intro to rx and its been super helpful with getting up to speed with the framework.
在关于BehaviourSubject的部分中,以下是提到:
In the section about BehaviourSubject, the following is mentioned:
BehaviorSubject< T> s
通常与班级相关联 属性 。
由于它们始终具有值并且可以提供更改通知,因此它们可能是将字段备份到属性的候选者。
我想询问人们是否发现这种实用性,如果是这样的话你在用它吗?我无法看到
获取monad之外的当前值的方式,这意味着将其绑定到WPF视图将会很棘手,而无需在订阅中填充值的额外副本。
Dan
推荐答案
嗨Dan,
您可以使用
First 运算符来提取来自 BehaviorSubject< T> 的值。
You can use the First operator to extract a value from a BehaviorSubject<T>.
或者,如果您使用的是 Rxx ,然后考虑使用
订阅扩展来定义两个由主题支持的-way绑定。 此扩展程序 表现类似于 正常的
和 IObserver< T> 界面。 因为&的 ISubject< T>
实现了这两个界面,它可以轻松地使用
BehaviorSubject< T> 推送新值,同时通过订阅从UI接收更新主题,或者如果您需要将问题分开,则通过创建不同的
主题< T > 或自定义观察者。
Alternatively, if you're using Rxx, then consider using the Subscription extension to define a two-way binding backed by subjects. This extension behaves similar to a normal Binding except that it understands the IObservable<T> and IObserver<T> interfaces for communicating changes. Since ISubject<T> implements both of these interfaces, it makes it easy to push new values using a BehaviorSubject<T> while receiving updates from the UI by subscribing to the subject, or if you need to separate concerns, then by creating a different Subject<T> or a custom observer.
这是一个实验室,说明如何使用
订阅执行单向和单向源绑定 扩展程序:
Here's a lab illustrating how to perform one-way and one-way-to-source bindings using the Subscription extension:
这是一个新的示例,说明如何使用 BehaviorSubject< T> 执行双向绑定。 我将此实验室添加到Rxx的下一个版本。
Here's a new example of how to use a BehaviorSubject<T> to perform a two-way binding. I'll add this lab to the next version of Rxx.
XAML: (请注意 BaseLab 就像普通的
UserControl 。 这里没什么特别的。)
<local:BaseLab x:Class="Rxx.Labs.UI.TwoWaySubscriptionLab"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:local="clr-namespace:Rxx.Labs"
xmlns:rxx="clr-namespace:System.Windows.Reactive;assembly=Rxx"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<StackPanel VerticalAlignment="Center">
<Label Content="Current value:" />
<TextBox Margin="20 0" Text="{Binding CurrentValue}" IsReadOnly="True" />
<Button Margin="0 20" HorizontalAlignment="Center" Content="Set Current Time" Click="SetTextToCurrentTime" />
<Label Content="Enter text here:" />
<TextBox Margin="20 0" Text="{rxx:Subscription Text, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</local:BaseLab>
代码背后:
using System;
using System.Reactive.Subjects;
using System.Windows;
namespace Rxx.Labs.UI
{
public partial class TwoWaySubscriptionLab : BaseLab
{
public static readonly DependencyProperty CurrentValueProperty = DependencyProperty.Register(
"CurrentValue",
typeof(string),
typeof(TwoWaySubscriptionLab),
new PropertyMetadata("Default Value"));
// This property is here just to prove that the Subscription binding is working.
public string CurrentValue
{
get
{
return (string) GetValue(CurrentValueProperty);
}
set
{
SetValue(CurrentValueProperty, value);
}
}
public ISubject<string, string> Text
{
get
{
return text;
}
}
private readonly BehaviorSubject<string> text = new BehaviorSubject<string>("Default Value");
public TwoWaySubscriptionLab()
{
InitializeComponent();
// Having an observable for UI input makes it easy to compose complicated queries against several properties.
// For example, you could write a query using the CombineLatest operator to be notified when any property
// is updated and passes validation. Then you can automatically take action, without requiring the user to
// press a button.
// Assigning CurrentValue isn't necessary, it simply proves that the Subscription binding is working.
text.Subscribe(value => CurrentValue = value);
}
private void SetTextToCurrentTime(object sender, RoutedEventArgs e)
{
var time = DateTime.Now.ToLongTimeString();
text.OnNext(time);
// We'll keep this in sync; otherwise, it looks strange to the user.
CurrentValue = time;
}
}
}
这是另一个关于如何使用两个主题执行双向绑定的新例子。 我将此实验室添加到Rxx的下一个版本。
Here's another new example of how to use two subjects to perform a two-way binding. I'll add this lab to the next version of Rxx.
XAML: (与上述相同)
代码背后:
using System;
using System.Reactive.Subjects;
using System.Windows;
namespace Rxx.Labs.UI
{
public partial class TwoWaySubscriptionLab : BaseLab
{
public static readonly DependencyProperty CurrentValueProperty = DependencyProperty.Register(
"CurrentValue",
typeof(string),
typeof(TwoWaySubscriptionLab),
new PropertyMetadata("Default Value"));
// This property is here just to prove that the Subscription binding is working.
public string CurrentValue
{
get
{
return (string) GetValue(CurrentValueProperty);
}
set
{
SetValue(CurrentValueProperty, value);
}
}
public ISubject<string, string> Text
{
get
{
return Subject.Create<string, string>(textFromUser, text);
}
}
private readonly BehaviorSubject<string> text = new BehaviorSubject<string>("Default Value");
private readonly Subject<string> textFromUser = new Subject<string>();
public TwoWaySubscriptionLab()
{
InitializeComponent();
// Having an observable for UI input makes it easy to compose complicated queries against several properties.
// For example, you could write a query using the CombineLatest operator to be notified when any property
// is updated and passes validation. Then you can automatically take action, without requiring the user to
// press a button.
//
// Here, we're just simulating a property with a backing field (text).
// Updating the BehaviorSubject<T> is like assiging the value to a backing field of a normal property.
textFromUser.Subscribe(value => text.OnNext(value));
// Assigning CurrentValue isn't necessary, it simply proves that the Subscription binding is working.
textFromUser.Subscribe(value => CurrentValue = value);
}
private void SetTextToCurrentTime(object sender, RoutedEventArgs e)
{
var time = DateTime.Now.ToLongTimeString();
text.OnNext(time);
// We'll keep this in sync; otherwise, it looks strange to the user.
CurrentValue = time;
}
}
}
- 戴夫
这篇关于行为主题为WPF ViewModel支持字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!