【问题标题】:Making WPF navigation dynamic - using an XML file?使 WPF 导航动态 - 使用 XML 文件?
【发布时间】:2012-04-23 13:11:02
【问题描述】:

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

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

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

谢谢!

【问题讨论】:

    标签: c# wpf xml navigation


    【解决方案1】:

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

    看看Microsoft Extensibility Framework (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-liner (!) 来组装所有导入的类甚至可能就足够了(这使用与以下参考教程不同的方法):

    CompositionInitializer.SatisfyImports(this);
    

    就是这样!

    (不要照原样接受这些例子,我只是想切入正题。我建议使用 Properties 而不是 stringsinterfaces 而不是类导出。你会在网上找到很多更优雅的 sn-ps。 :-) )

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

    【讨论】:

    • 今天早上在这方面工作了一段时间,让它运行起来,这是一个很好的解决方案!非常感谢!我一直停留在 XML 的思维模式中,但这是一种更简洁的导航处理方式。
    • @AmadeusHein:很高兴能帮上忙。 MEF 非常适合很多用途。尽管过去两年我已经在一些项目中使用过它,但我现在才真正深入了解它。我不知道为什么我这么长时间都试图避免 MEF...
    【解决方案2】:

    为什么不使用反射?

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

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

    【讨论】:

      猜你喜欢
      • 2019-08-03
      • 2022-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-12
      • 2015-08-31
      相关资源
      最近更新 更多