行为主题为WPF ViewModel支持字段 [英] Behaviour Subject as WPF ViewModel backing field

查看:51
本文介绍了行为主题为WPF ViewModel支持字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在阅读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绑定。  此扩展程序 表现类似于 正常的
Binding ,除了它理解 IObservable< T>用于沟通变更的
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:

XAML

背后的代码

这是一个新的示例,说明如何使用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆