2

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

目前我正在使用 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 处理的)。

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

谢谢!

4

2 回答 2

2

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

查看Microsoft 可扩展性框架 (MEF)。它适用于 WPF 和 MVVM。

它允许您在运行过程中轻松地即时编写应用程序部分。

简而言之,您可以使用 Attribute 标记要加载到其他地方的类[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而不是类导出。你会在网上找到很多更优雅的片段。:-))

您可以在此处找到 入门教程:Managed Extensibility Framework (MEF) 入门

于 2012-04-23T14:52:26.220 回答
0

为什么不使用反射?

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

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

object obj = Activator.CreateInstance(asmName, typeName).Unwrap() as UserControl;
于 2012-04-23T14:14:37.573 回答