【发布时间】:2021-05-26 01:38:32
【问题描述】:
我的应用程序基类中有 Xamarin 内容页面和视图模型,以便可以继承通用代码。我正在将 ReactiveUI 合并到此框架中,并希望能够在 WhenActivated 子句中引用特定于适当视图模型的属性,但是由于 Reactive ViewModel 属性基于 ReactiveContentPage 中给出的类型,因此在尝试这样做时遇到了问题,但我有那个类型作为基本类型。
我在下面创建了一个使用 ReactiveUI.XamForms nuget 的最小可重现示例。
视图模型和关联的基础视图模型:
public class BaseViewModel : ReactiveObject
{
}
public class MainPageViewModel : BaseViewModel
{
private string _result;
public string Result
{
get => _result;
set => this.RaiseAndSetIfChanged(ref _result, value);
}
private string _username;
public string UserName
{
get => _username;
set => this.RaiseAndSetIfChanged(ref _username, value);
}
public ReactiveCommand<Unit, Unit> RegisterCommand { get; }
public MainPageViewModel()
{
RegisterCommand = ReactiveCommand
.CreateFromObservable(ExecuteRegisterCommand);
}
private IObservable<Unit> ExecuteRegisterCommand()
{
Result = "Hello, " + UserName;
return Observable.Return(Unit.Default);
}
}
查看后面的代码:
public partial class MainPage : BasePage
{
public MainPage()
{
InitializeComponent();
BindingContext = new MainPageViewModel();
this.WhenActivated(disposable =>
{
this.Bind(ViewModel, x => x.UserName, x => x.Username.Text)
.DisposeWith(disposable);
this.BindCommand(ViewModel, x => x.RegisterCommand, x => x.Register)
.DisposeWith(disposable);
this.Bind(ViewModel, x => x.Result, x => x.Result.Text)
.DisposeWith(disposable);
});
}
}
查看 XAML:
<local:BasePage
x:Class="ReactiveUIXamarin.MainPage"
xmlns:local="clr-namespace:ReactiveUIXamarin;assembly=ReactiveUIXamarin"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
xmlns="http://xamarin.com/schemas/2014/forms"
ios:Page.UseSafeArea="true">
<StackLayout>
<Entry x:Name="Username" Placeholder="Username"/>
<Button x:Name="Register" Text="Go" TextColor="White" BackgroundColor="Gray" />
<Label x:Name="Result" />
</StackLayout>
</local:BasePage>
用于查看的关联基本页面:
//if you replace below with ReactiveContentPage<MainPageViewModel> then it compiles, but want to keep this
//with BaseViewModel so that all pages can inherit from this
public class BasePage : ReactiveContentPage<BaseViewModel>
{
}
如上面代码注释中所述,将 ReactiveContentPage
所以问题出在后面的视图代码上,因为即使在运行时 ReactiveUI ViewModel 属性实际上是一个 MainPageViewModel 对象,它在编译时并不知道这一点。所以我尝试将 ViewModel 转换为派生类型:
this.WhenActivated(disposable =>
{
this.Bind((MainPageViewModel)ViewModel, x => x.UserName, x => x.Username.Text)
.DisposeWith(disposable);
this.BindCommand((MainPageViewModel)ViewModel, x => x.RegisterCommand, x => x.Register)
.DisposeWith(disposable);
this.Bind((MainPageViewModel)ViewModel, x => x.Result, x => x.Result.Text)
.DisposeWith(disposable);
});
编译器可以使用 Bind 方法,但我无法弄清楚的是 BindCommand 方法。 它给出了以下编译错误:
类型“ReactiveUIXamarin.MainPage”不能用作类型参数 泛型类型或方法中的“TView” 'CommandBinder.BindCommand
(TView, TViewModel?, 表达式 >, 表达式 >, 字符串?)'。没有隐含的 从 'ReactiveUIXamarin.MainPage' 到的引用转换 'ReactiveUI.IViewFor '。
它正在尝试从 MainPage 转换为 MainPageViewModel,我只想将 BaseViewModel 转换为 MainPageViewModel。
如何更改 BindCommand 语句以使其正常工作?
【问题讨论】:
-
BindCommand 不能引用 RegisterCommand,因为没有强制转换 ViewModel 引用的是 BaseViewModel。在这种情况下返回的消息是:“BaseViewModel”不包含“RegisterCommand”的定义,并且没有可访问的扩展方法“RegisterCommand”接受“BaseViewModel”类型的第一个参数
-
啊,我误会了。我有一段时间没有绑定了;我认为这是内置类型中的一种方法。