WPF、MEF、Prism - 如何在 shell 中设置 DataContext
WPF,MEF,Prism - How to set DataContext in shell
我正在使用 WPF/PRISM/MEF 作为桌面应用程序。
这是一个具有三个区域的简单测试应用程序。视图定义在
一个外部模块。
看来我需要设置 shell DataContext。所以我将它设置为一个视图模型
如下图所示 - 应用程序运行正常。
我不满意做出明确的定义。是不是不可能
在初始化期间,加载一些模块,并找到一些视图并将其分配给
我的 shell 的 DataContext?我在哪里可以找到文档 - 我一定是错过了
在开发人员指南(和示例应用程序)中。或者,有人有什么建议吗?
Shell.xaml:
<Window x:Class="TestMenuTaskbarDT.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://www.codeplex.com/prism"
xmlns:local_viewmodels="clr-namespace:TestMenuTaskbarModuleMain.ViewModels;assembly=TestMenuTaskbarModuleMain"
. . .
>
<Window.InputBindings>
<KeyBinding Key="S" Modifiers="Control" Command="{Binding Path=CloseProjectCommand}" />
<KeyBinding Key="O" Modifiers="Control" Command="{Binding Path=OpenProjectCommand}" />
</Window.InputBindings>
<StackPanel>
<ItemsControl Name="MainMenuRegion" prism:RegionManager.RegionName="MainMenuRegion" />
<ItemsControl Name="MainToolbarRegion" prism:RegionManager.RegionName="MainToolbarRegion" />
<ItemsControl Name="MainContentRegion" prism:RegionManager.RegionName="MainContentRegion" />
</StackPanel>
<!-- How does one set the datacontext, when it should be dynamically loaded? -->
<Window.DataContext>
<local_viewmodels:MainWindowViewModel />
</Window.DataContext>
</Window>
(或者应该 local_viewmodels ... 放在资源中并以某种方式设置在那里?)
然后我可以在 Bootstrapper 中添加如下内容吗?或者是否有完全不同的技术?
Bootstrapper.cs :
. . .
class Bootstrapper : MefBootstrapper
{
. . .
protected override IModuleCatalog CreateModuleCatalog()
{
// All dlls are expected to reside in the same directory as the *.exe
return new DirectoryModuleCatalog() { ModulePath = System.AppDomain.CurrentDomain.BaseDirectory };
}
protected override void ConfigureAggregateCatalog()
{
base.ConfigureAggregateCatalog();
this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));
// Module registration remains the same *IT* registers the views with the region catalog
this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(TestMenuTaskbarModuleMain.TestMenuTaskbarModuleMain).Assembly));
}
. . .
protected override void InitializeShell()
{
base.InitializeShell();
Application.Current.MainWindow = (Window)this.Shell;
// Is something like the following possible?
_MyBaseViewModel = GetAViewModelSomehowFromAModule("MyViewModelKey");
Application.Current.MainWindow.DataContext = _MyBaseViewModel;
//
Application.Current.MainWindow.Show(); // Displays MainWindow
}
在我的 Shell.xaml.cs 中,我定义了这个 属性:
[Import]
ShellViewModel ViewModel
{
set
{
this.DataContext = value;
}
}
然后在我的 ShellViewModel class 中,构造函数将像这样装饰...
[Export]
public class ShellViewModel
于是依靠MEF组合import/export属性来实现DataContext设置。这是一个简化的示例,但您可能想进一步研究它,了解组合的多样性错误等。
如果我了解 Dynamoid,我应该使用以下内容:
namespace TestMenuTaskbarDT
{
[Export]
public partial class Shell : Window
{
[ImportingConstructor] public Shell([Import("ShellViewModel")]object aShellViewModel)
{
InitializeComponent();
//NOTE: DataContext is magically set from the imported object "aShellViewModel."
// I assume MEF uses Reflection to magically resolve all internal references.
DataContext = aShellViewModel;
}
/* removed, ImportingConstructor does it all in one step.
Note: DataContext is magically set from "value."
[Import("ShellViewModel")]
public object ViewModel
{
set { this.DataContext = value; }
}
*/
}
}
很明显,一步构造和初始化比先构造再初始化的两步形式更简单。 (所以人们应该点击 dynamoids 的评论来给予他应有的评价——不仅仅是因为他的暗示,还因为他坚持不懈地表达他的观点。)
(这里唯一剩下的就是让它在设计时正确显示 - 但这是一个不同的混乱。)
我正在使用 WPF/PRISM/MEF 作为桌面应用程序。
这是一个具有三个区域的简单测试应用程序。视图定义在 一个外部模块。
看来我需要设置 shell DataContext。所以我将它设置为一个视图模型 如下图所示 - 应用程序运行正常。
我不满意做出明确的定义。是不是不可能 在初始化期间,加载一些模块,并找到一些视图并将其分配给 我的 shell 的 DataContext?我在哪里可以找到文档 - 我一定是错过了 在开发人员指南(和示例应用程序)中。或者,有人有什么建议吗?
Shell.xaml:
<Window x:Class="TestMenuTaskbarDT.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://www.codeplex.com/prism"
xmlns:local_viewmodels="clr-namespace:TestMenuTaskbarModuleMain.ViewModels;assembly=TestMenuTaskbarModuleMain"
. . .
>
<Window.InputBindings>
<KeyBinding Key="S" Modifiers="Control" Command="{Binding Path=CloseProjectCommand}" />
<KeyBinding Key="O" Modifiers="Control" Command="{Binding Path=OpenProjectCommand}" />
</Window.InputBindings>
<StackPanel>
<ItemsControl Name="MainMenuRegion" prism:RegionManager.RegionName="MainMenuRegion" />
<ItemsControl Name="MainToolbarRegion" prism:RegionManager.RegionName="MainToolbarRegion" />
<ItemsControl Name="MainContentRegion" prism:RegionManager.RegionName="MainContentRegion" />
</StackPanel>
<!-- How does one set the datacontext, when it should be dynamically loaded? -->
<Window.DataContext>
<local_viewmodels:MainWindowViewModel />
</Window.DataContext>
</Window>
(或者应该 local_viewmodels ... 放在资源中并以某种方式设置在那里?)
然后我可以在 Bootstrapper 中添加如下内容吗?或者是否有完全不同的技术?
Bootstrapper.cs :
. . .
class Bootstrapper : MefBootstrapper
{
. . .
protected override IModuleCatalog CreateModuleCatalog()
{
// All dlls are expected to reside in the same directory as the *.exe
return new DirectoryModuleCatalog() { ModulePath = System.AppDomain.CurrentDomain.BaseDirectory };
}
protected override void ConfigureAggregateCatalog()
{
base.ConfigureAggregateCatalog();
this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));
// Module registration remains the same *IT* registers the views with the region catalog
this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(TestMenuTaskbarModuleMain.TestMenuTaskbarModuleMain).Assembly));
}
. . .
protected override void InitializeShell()
{
base.InitializeShell();
Application.Current.MainWindow = (Window)this.Shell;
// Is something like the following possible?
_MyBaseViewModel = GetAViewModelSomehowFromAModule("MyViewModelKey");
Application.Current.MainWindow.DataContext = _MyBaseViewModel;
//
Application.Current.MainWindow.Show(); // Displays MainWindow
}
在我的 Shell.xaml.cs 中,我定义了这个 属性:
[Import]
ShellViewModel ViewModel
{
set
{
this.DataContext = value;
}
}
然后在我的 ShellViewModel class 中,构造函数将像这样装饰...
[Export]
public class ShellViewModel
于是依靠MEF组合import/export属性来实现DataContext设置。这是一个简化的示例,但您可能想进一步研究它,了解组合的多样性错误等。
如果我了解 Dynamoid,我应该使用以下内容:
namespace TestMenuTaskbarDT
{
[Export]
public partial class Shell : Window
{
[ImportingConstructor] public Shell([Import("ShellViewModel")]object aShellViewModel)
{
InitializeComponent();
//NOTE: DataContext is magically set from the imported object "aShellViewModel."
// I assume MEF uses Reflection to magically resolve all internal references.
DataContext = aShellViewModel;
}
/* removed, ImportingConstructor does it all in one step.
Note: DataContext is magically set from "value."
[Import("ShellViewModel")]
public object ViewModel
{
set { this.DataContext = value; }
}
*/
}
}
很明显,一步构造和初始化比先构造再初始化的两步形式更简单。 (所以人们应该点击 dynamoids 的评论来给予他应有的评价——不仅仅是因为他的暗示,还因为他坚持不懈地表达他的观点。)
(这里唯一剩下的就是让它在设计时正确显示 - 但这是一个不同的混乱。)