ReactiveProperty.XamariniOS 9.5.0
dotnet add package ReactiveProperty.XamariniOS --version 9.5.0
NuGet\Install-Package ReactiveProperty.XamariniOS -Version 9.5.0
<PackageReference Include="ReactiveProperty.XamariniOS" Version="9.5.0" />
paket add ReactiveProperty.XamariniOS --version 9.5.0
#r "nuget: ReactiveProperty.XamariniOS, 9.5.0"
// Install ReactiveProperty.XamariniOS as a Cake Addin #addin nuget:?package=ReactiveProperty.XamariniOS&version=9.5.0 // Install ReactiveProperty.XamariniOS as a Cake Tool #tool nuget:?package=ReactiveProperty.XamariniOS&version=9.5.0
ReactiveProperty
ReactiveProperty 在 Reactive Extensions 下提供 MVVM 和异步支持功能。目标框架为 .NET 6.0+、.NET Framework 4.7.2 和 .NET Standard 2.0。
注意
如果您正在开发新的应用程序,请考虑使用 R3 而不是 ReactiveProperty。R3 是由原始作者重新设计的,与当前的 .NET 生态系统保持一致,并提供了与 ReactiveProperty 大多数功能相似的功能。
概念
ReactiveProperty 是一个非常强大且简单的库。
此示例应用程序的 ViewModel 代码如下
public class MainPageViewModel
{
public ReactivePropertySlim<string> Input { get; }
public ReadOnlyReactivePropertySlim<string> Output { get; }
public MainPageViewModel()
{
Input = new ReactivePropertySlim<string>("");
Output = Input
.Delay(TimeSpan.FromSeconds(1))
.Select(x => x.ToUpper())
.ObserveOnDispatcher()
.ToReadOnlyReactivePropertySlim();
}
}
它非常简单易懂(我认为!)因为它没有基类和接口。只是在输入属性和输出属性之间有声明性代码。
所有步骤都在 ReactiveProperty 文档 的 "入门" 部分中进行了说明。
ReactiveProperty 的概念很简单,是一个名为 ReactiveProperty[Slim]
的核心类,它只是一个封装有值的类,并实现了 IObservable<T>
和 INotifyPropertyChanged
。其中 IObservable<T>
用于将属性值的变化事件连接到 Rx LINQ 方法变化,而 INotifyPropertyChanged
用于数据绑定系统,如 WPF、WinUI 和 MAUI。
ReactiveProperty 的一个重要概念是 "Fun programming"。使用 ReactiveProperty 的 ViewModel 代码非常简单。
ViewModel 的常用实现
public class AViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _name;
public string Name
{
get => _name;
set
{
_name = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
// Update a command status
DoSomethingCommand.RaiseCanExecuteChanged();
}
}
private string _memo;
public string Memo
{
get => _memo;
set
{
_memo = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Memo)));
// Update a command status
DoSomethingCommand.RaiseCanExecuteChanged();
}
}
// DelegateCommand is plane ICommand implementation.
public DelegateCommand DoSomethingCommand { get; }
public AViewModel()
{
DoSomethingCommand = new DelegateCommand(
() => { ... },
() => !string.IsNullOrEmpty(Name) && !string.IsNullOrEmpty(Memo)
);
}
}
绑定代码
<TextBlock Text="{Binding Name}">
<TextBlock Text="{Binding Memo}">
使用 ReactiveProperty 实现ViewModel
public class AViewModel
{
public ValidatableReactiveProperty<string> Name { get; }
public ValidatableReactiveProperty<string> Memo { get; }
public ReactiveCommandSlim DoSomethingCommand { get; }
public AViewModel()
{
Name = new ValidatableReactiveProperty<string>("",
x => string.IsNullOrEmpty(x) ? "Invalid value" : null);
Memo = new ValidatableReactiveProperty<string>("",
x => string.IsNullOrEmpty(x) ? "Invalid value" : null);
DoSomethingCommand = new[]
{
Name.ObserveHasErrors,
Memo.ObserveHasErrors,
}
.CombineLatestValuesAreAllFalse()
.ToReactiveCommand()
.WithSubscribe(() => { ... });
}
}
绑定代码
<TextBlock Text="{Binding Name.Value}">
<TextBlock Text="{Binding Memo.Value}">
非常简单。
ReactiveProperty并不在ViewModel中提供基类,这意味着ReactiveProperty可以与Prism、Microsoft.Toolkit.Mvvm等其他MVVM库协同使用。
文档
NuGet包
包ID | 版本和下载 | 描述 |
---|---|---|
ReactiveProperty | 该包包含所有核心特性。 | |
ReactiveProperty.Core | 该包包含如 ReactivePropertySlim<T> 和 ReadOnlyReactivePropertySlim<T> 等最小化类。并且这没有任何依赖于System.Reactive。如果你不需要Rx特性,那么它很适用。 |
|
ReactiveProperty.WPF | 该包包含了适用于WPF的 EventToReactiveProperty 和 EventToReactiveCommand。这是.NET 6或更高版本和.NET Framework 4.7.2或更高版本。 | |
ReactiveProperty.Blazor | 该包包含了ReactiveProperty验证特性对Blazor EditForm组件的支持。这是.NET 6.0或更高版本。 |
以下包处于维护阶段。
包ID | 版本和下载 | 描述 |
---|---|---|
ReactiveProperty.UWP | 该包包含了适用于UWP的 EventToReactiveProperty 和 EventToReactiveCommand。 | |
ReactiveProperty.XamarinAndroid | 该包包含了许多将事件创建为IObservable的扩展方法,用于Xamarin.Android原生。 | |
ReactiveProperty.XamariniOS | 该包包含了许多将ReactiveProperty和ReactiveCommand绑定到Xamarin.iOS原生控件上的扩展方法。 |
支持
我不会关注StackOverflow和其他论坛以支持ReactiveProperty,因此请随时在Github issues中发布问题。我会使用日语(第一语言)和英语(第二语言)。
如果发布的问题太多,那么我计划将关于功能请求、问题、问题的发布地点分开。
作者信息
Yoshifumi Kawai,又名 @neuecc,是位于日本东京的Cysharp,Inc的创始人/CEO/CTO。自2011年4月起获得Microsoft MVP for Developer Technologies奖项。他是ReactiveProperty的原始拥有者。
Takaaki Suzuki,又名 @xin9le,是位于日本福井的软件开发者。自2012年7月起获得Microsoft MVP for Developer Technologies奖项。
Kazuki Ota,又名 @okazuki,是位于日本东京的软件开发者。自2011年7月至2017年2月获得Microsoft MVP for Windows Development奖项。现在,他在微软日本工作。
产品 | 版本 兼容和附加的目标框架版本。 |
---|---|
.NET | net7.0-ios16.1 是兼容的。 net8.0-ios 已计算。 net8.0-ios17.2 是兼容的。 |
-
net7.0-ios16.1
- ReactiveProperty (>= 9.5.0)
-
net8.0-ios17.2
- ReactiveProperty (>= 9.5.0)
NuGet包
此包未由任何NuGet包使用。
GitHub仓库
此包未由任何流行的GitHub仓库使用。
版本 | 下载 | 上次更新 |
---|---|---|
9.5.0 | 103 | 2/28/2024 |
9.4.1 | 96 | 2/12/2024 |
9.4.0 | 101 | 2/11/2024 |
9.4.0-pre8 | 135 | 12/21/2023 |
9.4.0-pre7 | 83 | 12/21/2023 |
9.4.0-pre6 | 84 | 12/21/2023 |
9.4.0-pre5 | 81 | 12/21/2023 |
9.4.0-pre4 | 81 | 12/21/2023 |
9.3.4 | 244 | 10/30/2023 |
9.3.4-pre202310290551 | 92 | 10/29/2023 |
9.3.3 | 135 | 10/10/2023 |
9.3.2 | 129 | 9/25/2023 |
9.3.2-pre202309140728 | 103 | 9/14/2023 |
9.3.1 | 176 | 8/11/2023 |
9.3.0 | 165 | 7/31/2023 |
9.3.0-pre202307291429 | 141 | 7/29/2023 |
9.2.0 | 179 | 6/19/2023 |
9.2.0-pre202305241301 | 131 | 5/25/2023 |
9.1.2 | 260 | 3/12/2023 |
9.0.0 | 308 | 2/12/2023 |
9.0.0-pre202302040959 | 123 | 2/4/2023 |
9.0.0-pre202301080724 | 166 | 1/8/2023 |
9.0.0-pre202301050852 | 142 | 1/5/2023 |
8.2.0 | 366 | 11/10/2022 |
8.1.2 | 1,072 | 6/6/2022 |
8.1.2-pre202206051057 | 161 | 6/5/2022 |
8.1.1 | 450 | 5/27/2022 |
8.1.0 | 448 | 4/30/2022 |
8.1.0-pre202204290912 | 164 | 4/29/2022 |
8.1.0-pre202204290644 | 148 | 4/29/2022 |
8.0.5 | 444 | 3/24/2022 |
8.0.5-pre202203191529 | 174 | 3/19/2022 |
8.0.5-pre202203191312 | 152 | 3/19/2022 |
8.0.4 | 443 | 3/5/2022 |
8.0.4-pre202203040658 | 163 | 3/4/2022 |
8.0.3 | 349 | 12/5/2021 |
8.0.3-pre202112031043 | 872 | 12/3/2021 |
8.0.3-pre202112030833 | 831 | 12/3/2021 |
8.0.2 | 915 | 11/21/2021 |
8.0.1 | 522 | 11/20/2021 |
8.0.1-pre202111200140 | 565 | 11/20/2021 |
8.0.0 | 340 | 11/9/2021 |
8.0.0-pre202111090825 | 205 | 11/9/2021 |
8.0.0-pre202110240626 | 250 | 10/24/2021 |
8.0.0-pre202110161410 | 304 | 10/16/2021 |
8.0.0-pre202110160852 | 222 | 10/16/2021 |
8.0.0-pre202110160831 | 233 | 10/16/2021 |
8.0.0-pre202110131323 | 238 | 10/13/2021 |
8.0.0-pre202110071401 | 268 | 10/7/2021 |
8.0.0-pre202110060758 | 232 | 10/6/2021 |
8.0.0-pre202110060735 | 208 | 10/6/2021 |
8.0.0-pre202109190434 | 293 | 9/19/2021 |
8.0.0-pre202109160117 | 246 | 9/16/2021 |
8.0.0-pre202108141424 | 274 | 8/14/2021 |
8.0.0-pre202107040319 | 243 | 7/4/2021 |
7.12.0 | 3,742 | 8/6/2021 |
7.11.0 | 478 | 5/31/2021 |
7.10.0 | 401 | 4/29/2021 |
7.9.0 | 402 | 4/20/2021 |
7.8.3 | 1,342 | 3/24/2021 |
7.8.2 | 365 | 3/23/2021 |
7.8.1 | 421 | 3/11/2021 |
7.8.1-pre202103031133 | 257 | 3/3/2021 |
7.8.0 | 397 | 2/21/2021 |
7.8.0-pre202102210255 | 222 | 2/21/2021 |
7.8.0-pre202102201703 | 243 | 2/20/2021 |
7.7.1 | 408 | 2/19/2021 |
7.7.1-pre202102190925 | 218 | 2/19/2021 |
7.7.0 | 420 | 1/26/2021 |
7.6.1 | 400 | 1/15/2021 |
7.6.0 | 424 | 1/13/2021 |
7.5.1 | 542 | 10/19/2020 |
7.5.0 | 471 | 10/17/2020 |
7.5.0-pre202010141113 | 283 | 10/14/2020 |
7.4.1 | 486 | 9/23/2020 |
7.4.0 | 505 | 9/18/2020 |
7.3.0 | 490 | 9/17/2020 |
7.2.1 | 501 | 9/11/2020 |
7.2.0 | 498 | 8/4/2020 |
7.1.0 | 523 | 5/26/2020 |
7.1.0-pre202005251107 | 352 | 5/25/2020 |
7.0.1 | 512 | 5/14/2020 |
7.0.1-pre202005131606 | 332 | 5/13/2020 |
7.0.0 | 533 | 5/5/2020 |
7.0.0-ci20200503102823 | 366 | 5/3/2020 |
7.0.0-ci20200503100450 | 392 | 5/3/2020 |