假設我有以下看法型號:是否有一種模式可以用Reactive UI訂閱分層屬性更改?
public class AddressViewModel : ReactiveObject
{
private string line;
public string Line
{
get { return this.line; }
set { this.RaiseAndSetIfChanged(x => x.Line, ref this.line, value); }
}
}
public class EmployeeViewModel : ReactiveObject
{
private AddressViewModel address;
public AddressViewModel Address
{
get { return this.address; }
set { this.RaiseAndSetIfChanged(x => x.Address, ref this.address, value); }
}
}
現在假設在EmployeeViewModel
我要揭露與Address.Line
最新值的屬性:
public EmployeeViewModel()
{
this.changes = this.ObservableForProperty(x => x.Address)
.Select(x => x.Value.Line)
.ToProperty(this, x => x.Changes);
}
private readonly ObservableAsPropertyHelper<string> changes;
public string Changes
{
get { return this.changes.Value; }
}
這隻會打勾時更改產生Address
屬性,但在Address
內發生更改爲Line
時不會發生。如果我不是這樣做:
public EmployeeViewModel()
{
this.changes = this.Address.Changed
.Where(x => x.PropertyName == "Line")
.Select(x => this.Address.Line) // x.Value is null here, for some reason, so I use this.Address.Line instead
.ToProperty(this, x => x.Changes);
}
當電流AddressViewModel
內的變化Line
發生這樣只會蜱,但沒有考慮設置新AddressViewModel
共(也不適應null
Address
)。
我試圖讓我的頭繞着正確的方法來解決這個問題。我是RxUI的新手,所以我可能會錯過一些明顯的東西。我可能手動掛鉤到地址的變化,並設置二次訂閱,但這似乎醜陋和容易出錯。
有沒有一個標準模式或幫手,我應該用來實現這一目標?
下面是一些代碼,可以複製/粘貼嘗試了這一點:
ViewModels.cs:
namespace RxUITest
{
using System;
using System.Reactive.Linq;
using System.Threading;
using System.Windows.Input;
using ReactiveUI;
using ReactiveUI.Xaml;
public class AddressViewModel : ReactiveObject
{
private string line1;
public string Line1
{
get { return this.line1; }
set { this.RaiseAndSetIfChanged(x => x.Line1, ref this.line1, value); }
}
}
public class EmployeeViewModel : ReactiveObject
{
private readonly ReactiveCommand changeAddressCommand;
private readonly ReactiveCommand changeAddressLineCommand;
private readonly ObservableAsPropertyHelper<string> changes;
private AddressViewModel address;
private int changeCount;
public EmployeeViewModel()
{
this.changeAddressCommand = new ReactiveCommand();
this.changeAddressLineCommand = new ReactiveCommand();
this.changeAddressCommand.Subscribe(x => this.Address = new AddressViewModel() { Line1 = "Line " + Interlocked.Increment(ref this.changeCount) });
this.changeAddressLineCommand.Subscribe(x => this.Address.Line1 = "Line " + Interlocked.Increment(ref this.changeCount));
this.Address = new AddressViewModel() { Line1 = "Default" };
// Address-only changes
this.changes = this.ObservableForProperty(x => x.Address)
.Select(x => x.Value.Line1 + " CHANGE")
.ToProperty(this, x => x.Changes);
// Address.Line1-only changes
//this.changes = this.Address.Changed
// .Where(x => x.PropertyName == "Line1")
// .Select(x => this.Address.Line1 + " CHANGE") // x.Value is null here, for some reason, so I use this.Address.Line1 instead
// .ToProperty(this, x => x.Changes);
}
public ICommand ChangeAddressCommand
{
get { return this.changeAddressCommand; }
}
public ICommand ChangeAddressLineCommand
{
get { return this.changeAddressLineCommand; }
}
public AddressViewModel Address
{
get { return this.address; }
set { this.RaiseAndSetIfChanged(x => x.Address, ref this.address, value); }
}
public string Changes
{
get { return this.changes.Value; }
}
}
}
MainWindow.cs:
using System.Windows;
namespace RxUITest
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new EmployeeViewModel();
}
}
}
MainWindow.xaml:
<Window x:Class="RxUITest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBlock Text="{Binding Changes}"/>
<Button Command="{Binding ChangeAddressCommand}">Change Address</Button>
<Button Command="{Binding ChangeAddressLineCommand}">Change Address.Line1</Button>
</StackPanel>
</Window>
太精彩了!剛剛嘗試過,它工作。我誤解了'WhenAny'操作符觀察任何數量的「尾部」屬性(上例中的'Line')。我沒有意識到它也有智慧觀察連鎖店中的任何財產。謝謝保羅。 –
is this.RaiseAndSetIfChanged(x => x.Address,ref this.address,value);語法仍然支持?我只能得到以下語法; this.RaiseAndSetIfChanged(ref this.address,value); – Elangesh
不,舊的語法已過時,現在只應使用新的語法。 –