使 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 定位器来处理的)。
从技术上讲,此解决方案允许在不重新编译的情况下稍微更改导航(例如,您可以按照自己喜欢的任何方式打乱顺序),但必须有比匹配字符串属性更好的方法来处理此问题。我尝试过序列化用户控件,以便我可以将其与其他属性一起加载,但到目前为止,我没有运气。关于如何进行和改进/更改的任何想法?
谢谢!
确实,有更好的方法。
查看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
而不是strings
,interfaces
而不是类导出。你会在网上找到很多更优雅的片段。:-) )
在这里,您可以找到帮助您入门的教程:托管扩展性框架 (MEF) 入门
为什么不使用反射?
您可以使用Activator.CreateInstance
并传入视图的字符串:
string asmName = "YourAssembly";
string typeName = "YourViewName";
object obj = Activator.CreateInstance(asmName, typeName).Unwrap() as UserControl;