我正在寻找使用尊重 MVVM ReactiveUi 原则的参数打开新窗口的最佳方法。现在我正在使用 Splat 的服务位置来打开新窗口。 假设我想在单击主窗口视图上的按钮时打开新窗口。 目前:
但是如果我想向“WindowToOpen”传递参数该怎么办?
谢谢
我也找不到任何有关如何在 WPF 中使用 ReactiveUI 打开新窗口的示例。
我最终所做的是将依赖属性添加到我的视图中(因为您无法将参数传递给视图构造函数)。例如,如果您需要将字符串值
userName
传递到新窗口,则必须将以下依赖项属性添加到该视图类:
public static readonly DependencyProperty UserNameProperty =
DependencyProperty.Register("UserName", typeof(string), typeof(YourView),
new PropertyMetadata(default(string)));
public string UserName
{
get => (string) GetValue(UserNameProperty);
set => SetValue(UserNameProperty, value);
}
然后,在创建视图时,您可以为该属性分配一个值。对于你的情况:
Window window = Locator.Current.GetService("WindowToOpen") as Window;
window.PropertyToChange = valueOfProperty;
window.Show();
如果您需要视图模型中的属性值(如果您使用 MVVM,则可能会这样做),请将依赖项属性绑定到视图模型中的属性。这必须在视图的
WhenActivated
方法中完成:
this.WhenActivated(disposables =>
{
// Instantiate the view model just in case it is null
ViewModel ??= Locator.Current.GetService<YourView>() ??
throw new InvalidOperationException("YourViewis not registered.");
this.WhenAnyValue(view => view.UserName)
.BindTo(ViewModel, viewModel => viewModel.UserName)
.DisposeWith(disposables);
// other bindings
});
我知道这一切感觉非常笨重和混乱。但我还没有找到任何关于如何仅使用 ReactiveUI 正确完成此操作的示例。
在 ReactiveUI 中,您可以使用 IViewFor 或本例中的 ReactiveWindow
窗口服务逻辑:
这项服务可能是这样的:
public interface IWindowService
{
void OpenWindow<TViewModel>(TViewModel viewModel) where TViewModel : ReactiveObject;
}
public class WindowService : IWindowService
{
public void OpenWindow<TViewModel>(TViewModel viewModel) where TViewModel : ReactiveObject
{
var viewLocator = Locator.Current.GetService<IViewLocator>();
var view = viewLocator.ResolveView(viewModel);
if (view is not ReactiveWindow<TViewModel> window)
throw new Exception("ViewModel does not have associated Window");
window.ViewModel = viewModel;
window.Show();
}
}
你可以这样使用它
public class MainViewModel : ReactiveObject
{
public ReactiveCommand<Unit, Unit> OpenWindow { get; }
public MainViewModel(IWindowService? windowService = null)
{
this.windowService = windowService ?? Locator.Current.GetService<IWindowService>();
OpenWindow = ReactiveCommand.Create(() =>
{
var vm = new ExternalWindowViewModel(/*Add some parametrs*/);
this.windowService.OpenWindow(vm);
});
}
}
假设您的视图中有按钮或其他内容绑定到 OpenWindow 命令:
public partial class MainWindow : ReactiveWindow<MainViewModel>
{
public MainWindow()
{
InitializeComponent();
ViewModel = new MainViewModel();
this.WhenActivated(disposables =>
{
this.BindCommand(ViewModel, vm => vm.OpenWindow, v => v.NewWindowBtn)
.DisposeWith(disposables);
});
}
}
另外不要忘记将视图与视图模型相关联:
Locator.CurrentMutable.RegisterViewsForViewModels(Assembly.GetCallingAssembly());