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

时间:2012-04-23 13:11:02

标签: c# wpf xml navigation

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

目前我正在使用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属性来匹配和创建我的视图(它们也有一个ViewModel,但这是通过XAML和MVVM Light ViewModel Locator完成的。)

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

谢谢!

2 个答案:

答案 0 :(得分:2)

确实,有一种更好的方法。 : - )

查看Microsoft Extensibility Framework (MEF)。它适用于WPF和MVVM。

它允许您轻松地在runtine 中即时组合应用程序部分

简而言之,您使用属性[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-liner(!)来组装所有导入的类(这使用与以下引用教程不同的方法)甚至就足够了:

CompositionInitializer.SatisfyImports(this);

就是这样!

(请按原样采用这些示例,我只是想达到目的。我建议使用 Properties而不是stringsinterfaces而不是类导出。你会在网上找到更多优雅的片段。 :-))

在这里,您可以找到一个帮助您入门的教程: Getting started with Managed Extensibility Framework (MEF)

答案 1 :(得分:0)

为什么不使用反射?

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

string asmName = "YourAssembly";
string typeName = "YourViewName";

object obj = Activator.CreateInstance(asmName, typeName).Unwrap() as UserControl;