[英]Trouble with showing a Mahapps.Metro Dialog with a ReactiveUi Command
我正在尝试在我的项目中使用 Mahapps 对话框,但是当从我的 ViewModel 中的 ReactivUI 命令触发时无法让它们工作。在视图的 XAML 中,我已经注册了对话框。
xmlns:dialogs="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
dialogs:DialogParticipation.Register="{Binding}"
我还有一个绑定到 ShowDialog 命令的按钮。
this.BindCommand(viewModel, vm => vm.ShowDialog, x => x.button);
最后,在我的 ViewModel 中,我设置了 RxUI 命令和 dialogcoordinator 实例。
public MainWindowViewModel(IDialogCoordinator dialogCoordinator)
{
_dialogCoordinator = dialogCoordinator;
ShowDialog = ReactiveCommand.CreateFromTask(async () =>
{
await _dialogCoordinator.ShowMessageAsync(this, "Message from VM", "MVVM based dialogs!");
});
ShowDialog.ThrownExceptions.Subscribe(ex => Console.WriteLine(ex.ToString()));
}
无论我尝试过什么,它总是抛出相同的错误
System.InvalidOperationException: Context is not registered. Consider using DialogParticipation.Register in XAML to bind in the DataContext.
我不确定是否还需要其他任何东西才能使对话框正常工作,或者我是否只是错误地使用了 RxUI 中的命令
我在另一个 MVVM 框架(MVVM Light Toolkit)上遇到了同样的问题。 但是框架似乎不是问题。 这是时间问题。 DialogCoordinator 不能从构造函数访问。 我个人将所有代码从构造函数移动到正在被触发的 RelayCommand
<controls:MetroWindow
x:Class="UI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:dialog="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
dialog:DialogParticipation.Register="{Binding}"
DataContext="{Binding Source={StaticResource Locator}, Path=Main}"
d:DataContext="{d:DesignInstance vm:MainViewModel}"
mc:Ignorable="d">
<i:Interaction.Triggers>
<i:EventTrigger EventName="ContentRendered">
<i:InvokeCommandAction Command="{Binding StartupCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
我尝试了不同的事件,例如 Loaded,它在某些情况下有效,但“ContentRendered”始终在 VM 中有效,我有以下代码:
public ICommand StartupCommand
{
get
{
return new RelayCommand(async ()=>
{
this.AccountName = await
dialogCoordinator.ShowInputAsync(this, "Welcome", "Please insert your account name");
});
}
}
所以基本上它似乎还没有直接注册,但在加载内容后它是。 (在这个例子中,我使用了 ShowInputAsync 但它应该与 ShowMessageAsync 一样工作)
这似乎是一个时间问题 - 当我第一次开始玩这个时,我通过从 View 的 Loaded 事件而不是它的构造函数设置 VM 的 DialogCoordinator 实例来让它工作。
我已经在https://github.com/dwarry/ReactiveUiMahAppsDialog 上组合了一个最小的工作应用程序来演示这一点。 它使用 ReactiveUi 的正常交互机制来触发显示对话框。 与此保持一致,我已将其放在视图中,但我不明白为什么如果您愿意,它不能适应从 ViewModel 执行此操作。 要注意的另一件事是,您需要在离开交互处理程序之前等待对话框关闭,否则 ReactiveUI 将抛出 UnhandledInteractionException。
对我来说,使用ContentRendered
事件没有做任何事情; 我仍然收到异常InvalidOperationException: Context is not registered. Consider using DialogParticipation.Register in XAML to bind in the DataContext
InvalidOperationException: Context is not registered. Consider using DialogParticipation.Register in XAML to bind in the DataContext
。
我的解决方案基于 Kent Boogaart 的书籍样本。
看法:
using System.Reactive;
using System.Reactive.Disposables;
using System.Windows;
using MahApps.Metro.Controls;
using MahApps.Metro.Controls.Dialogs;
using ReactiveUI;
using Splat;
namespace ReactiveUIMahAppsDialog
{
public partial class ChildView
{
public ChildView()
{
InitializeComponent();
this.WhenActivated(disposables =>
{
ViewModel ??= Locator.Current.GetService<ChildViewModel>() ?? new ChildViewModel();
this.BindCommand(ViewModel,
viewModel => viewModel.LogInUser,
view => view.Test)
.DisposeWith(disposables);
this.ViewModel.Message
.RegisterHandler(async interaction =>
{
MetroWindow window = (MetroWindow) Window.GetWindow(this);
await window.ShowMessageAsync("test", "test");
interaction.SetOutput(Unit.Default);
})
.DisposeWith(disposables);
});
}
}
}
<reactiveUi:ReactiveUserControl
x:Class="ReactiveUIMahAppsDialog.ChildView"
x:TypeArguments="viewModels:ChildViewModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:reactiveUi="http://reactiveui.net"
xmlns:viewModels="clr-namespace:ReactiveUIMahAppsDialog"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Button x:Name="Test" Content="Show Dialog" Width="100" Height="100"/>
</Grid>
</reactiveUi:ReactiveUserControl>
在MetroWindow
托管反应式用户控件。
视图模型:
using System.Reactive;
using System.Reactive.Linq;
using ReactiveUI;
namespace ReactiveUIMahAppsDialog
{
public class ChildViewModel : ReactiveObject
{
public ChildViewModel()
{
Message = new Interaction<Unit, Unit>();
LogInUser = ReactiveCommand.CreateFromTask(async _ => await Message.Handle(Unit.Default));
}
public ReactiveCommand<Unit, Unit> LogInUser { get; }
public Interaction<Unit, Unit> Message { get; }
}
}
完整代码可以在这里找到。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.