我有一个对话服务
using RControl.Client.Abstractions;
using System;
using System.Windows;
namespace RControl.Client.Services;
public class DialogService : IDialogService
{
public void ShowDialog<TViewModel>(TViewModel viewModel)
{
var window = new Window
{
Content = Activator.CreateInstance(ViewLocator.GetViewType(typeof(TViewModel))),
DataContext = viewModel,
};
window.ShowDialog();
}
}
另见视图定位器
using System;
using System.Linq;
using System.Reflection;
namespace RControl.Client;
public static class ViewLocator
{
private const string ViewSuffix = "View";
private const string ViewModelSuffix = "ViewModel";
public static Type GetViewType(Type viewModelType)
{
var viewName = viewModelType.Name.Replace(ViewModelSuffix, string.Empty) + ViewSuffix;
var viewType = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(t => t.Name == viewName);
return viewType ?? throw new ArgumentException($"View not found for {viewModelType.Name}.");
}
}
但是当以这种方式使用该服务时
[RelayCommand]
private void About()
{
var viewModel = new AboutViewModel();
_dialogService.ShowDialog(viewModel);
}
抛出异常:系统操作无效异常:"Window对象必须是树的根。不能将Window对象添加为Visual的子对象。"
如何实现与相同的行为:
var window = new AboutView();
window.ShowDialog();
1条答案
按热度按时间7qhs6swi1#
你应该把你要在窗口中显示的视图做成一个用户控件,而不是做所有getviewtype的事情,定义数据模板,通过数据类型把每个视图和一个视图模型联系起来。
如果您想自动化它,可以在代码生成器中使用元数据来构建它。
但您的窗口可能类似于:
这个窗口可以用于任何你需要的窗口,它只是一个 shell ,包含你需要显示的任何东西。
关联用户控件:
这些数据模板放在app.xaml中合并的资源字典中。
然后,您可以新建该窗口的示例,将datacontext设置为MainViewModel示例,窗口的内容将模板化到MainUC示例中。
您可以显示这样一个窗口对话框。
显然,保留对视图模型的引用以获取任何用户输入。