使 WPF 导航动态化 - 使用 XML 文件

本文关键字:使用 XML 文件 动态化 WPF 导航 | 更新日期: 2023-09-27 18:32:08

我正在处理桌面应用程序的导航部分,遇到了一些问题。要求导航应该是动态的,以便您可以切换视图的顺序而无需重新编译(理想情况下,还可以在不重新编译的情况下添加视图)。

目前,我正在使用XML来定义要显示的窗口,它应该具有哪个页眉以及页脚的外观。下面是 XML 现在的外观:

<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfViewState xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ViewState ViewName="WelcomeView" Header="Welcome to the Application" FooterButton1="Quit" FooterButton2="Back" FooterButton3="Next" />
  <ViewState ViewName="LicenseView" Header="Licence Agreement" FooterButton1="Quit" FooterButton2="Back" FooterButton3="Next" />
  <ViewState ViewName="LoginView" Header="Log in" FooterButton1="Quit" FooterButton2="Back" FooterButton3="Next" />
  <ViewState ViewName="InstallationView" Header="Installing..." FooterButton1="Cancel" FooterButton2="None" FooterButton3="Next" />
  <ViewState ViewName="UpdateView" Header="Updating..." FooterButton1="Cancel" FooterButton2="None" FooterButton3="Next" />
  <ViewState ViewName="FinishedView" Header="Finished!" FooterButton1="None" FooterButton2="None" FooterButton3="Finish" />
</ArrayOfViewState>

当我在代码中匹配它时,它看起来像这样(viewState.View 的类型是 UserControl):

...
case "WelcomeView":
  viewState.View = new WelcomeView();
...

如您所见,我在 XML 中使用 ViewName 属性来匹配和创建我的视图(它们也有一个视图模型,但这是通过 XAML 和 MVVM Light ViewModel 定位器来处理的)。

从技术上讲,此解决方案允许在不重新编译的情况下稍微更改导航(例如,您可以按照自己喜欢的任何方式打乱顺序),但必须有比匹配字符串属性更好的方法来处理此问题。我尝试过序列化用户控件,以便我可以将其与其他属性一起加载,但到目前为止,我没有运气。关于如何进行和改进/更改的任何想法?

谢谢!

使 WPF 导航动态化 - 使用 XML 文件

确实,有更好的方法。

查看Microsoft扩展性框架 (MEF)。它与WPF和MVVM配合得很好。

它允许您在运行期间轻松即时组合应用程序部件。

简而言之,你用属性[Export]标记一个你想要加载到其他地方的类:

[Export(typeof(ViewContainer))]
public class ViewContainer
{
   public string ViewName = "WelcomeView";
   public string Header="Welcome to the Application"
   // Do more stuff here
}

在应使用导出类的类或程序集中,您可以使用 [Import] 属性加载它:

public class ClassInOtherAssembly
{
   [ImportMany]
   internal ObservableCollection<ViewContainer> m_MyViews { get; set; }
   // Do other stuff here
}

根据您实现的体系结构,使用1行(!)来组装所有导入的类甚至可能就足够了(这使用的方法与以下引用的教程不同):

CompositionInitializer.SatisfyImports(this);

就是这样!

不要按原样拿这些例子,我只是想进入正题。我建议使用 Properties而不是stringsinterfaces而不是类导出。你会在网上找到很多更优雅的片段。:-) )

在这里,您可以找到帮助您入门的教程:托管扩展性框架 (MEF) 入门

为什么不使用反射?

您可以使用Activator.CreateInstance并传入视图的字符串:

string asmName = "YourAssembly";
string typeName = "YourViewName";
object obj = Activator.CreateInstance(asmName, typeName).Unwrap() as UserControl;