gpt4 book ai didi

c# - ItemsControl 中的 PRISM View 注入(inject)

转载 作者:行者123 更新时间:2023-12-03 10:51:21 25 4
gpt4 key购买 nike

更新(2009 年 12 月 17 日):现在反射(reflect)了我取得的最新进展。

这是我和同事在 Silverlight 3.0 中使用 Prism 和 MVVM 开发的第一个应用程序。我正在为该项目开发一个外壳/框架,该项目将包含一个可以添加到“工作区”的“插件”列表。

插件在其特定的 PRISM IModule.Initialize() 方法中向 WorkSpaceManager 类注册,如下所示:

workspace.RegisterPlugin(new PluginInfo() { Name = "MyPlugin", ViewType = typeof(MyPluginView), SettingsViewType = null });

RegisterPlugin() 方法只是将 PluginInfo 对象添加到以“Name”属性为键的字典中。然后,当我想向工作区添加插件时,我执行以下操作:
workspace.AddPluginToWorkspace("MyPlugin");

WorkspaceManager 类的 AddPluginToWorkspace 方法如下所示:
public void AddPluginToWorkspace(string pluginName)
{
if (AvailablePlugins.ContainsKey(pluginName))
{
PluginInfo pi = AvailablePlugins[pluginName];
WorkspacePlugin wsp = new WorkspacePlugin();

// Create the View
wsp.View = (Control)this.unityContainer.Resolve(pi.ViewType);
wsp.Name = pi.Name;

// Wire up the CloseCommand to WorkspaceManager's PluginClosing handler
wsp.CloseCommand = new DelegateCommand<WorkspacePlugin>(this.PluginClosing);

// Add the plugin to the active plugins (modules) collection
this.modules.Add(wsp);

// FIX: This should notify anyone listening that the ActivePlugins have changed. When enabled, this causes the same error that will be mentioned further on when attempting to close a plugin.
//this.eventAggregator.GetEvent<ActivePluginsChanged>().Publish(wsp);
}

}

Workspace ViewModel 仅公开 WorkspaceManager 服务的模块集合,它是 Workspace View 的数据上下文,如下所示:
<Grid x:Name="LayoutRoot"
Background="White">
<ListBox x:Name="ModuleListBox"
Grid.Row="1"
rgn:RegionManager.RegionName="Workspace"
Background="Yellow"
ItemsSource="{Binding Plugins}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Template>
<ControlTemplate>
<Grid x:Name="ListBoxGrid">
<ItemsPresenter></ItemsPresenter>
</Grid>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black"
BorderThickness="2"
Margin="0"
Padding="0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="5"></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width=".05*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Content="X"
HorizontalAlignment="Right"
Grid.Column="1"
cmd:Click.Command="{Binding CloseCommand}"
cmd:Click.CommandParameter="{Binding}"></Button>
</Grid>
<Border BorderBrush="Black"
BorderThickness="2"
Margin="0"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Grid.Row="1">
<tk:Viewbox Stretch="Uniform"
StretchDirection="Both">
<ContentControl Content="{Binding View}"></ContentControl>
</tk:Viewbox>
</Border>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>

请注意绑定(bind)到 WorkspacePlugin 的“View”属性的 Content 控件以及将 Click.Command 绑定(bind)到“CloseCommand”的 Button。 这是我最初被卡住的地方,但在大多数情况下,这是可行的。插件的 View 加载在其他控件中,我仍然能够将关闭命令(以及稍后添加的其他命令)绑定(bind)到底层模型。

现在的问题是每当我单击关闭按钮并从模块集合中删除 WorkspacePlugin 时,都会在 ViewModel 上触发属性更改事件以让列表框知道要更新我收到以下错误(如果我取消注释下面的行也会发生这种情况上面的“修复”评论:

System.ArgumentException: Value does not fall within the expected range. at MS.Internal.XcpImports.CheckHResult(UInt32 hr) at MS.Internal.XcpImports.SetValue(INativeCoreTypeWrapper obj, DependencyProperty property, DependencyObject doh) at MS.Internal.XcpImports.SetValue(INativeCoreTypeWrapper doh, DependencyProperty property, Object obj) at System.Windows.DependencyObject.SetObjectValueToCore(DependencyProperty dp, Object value) at System.Windows.DependencyObject.RefreshExpression(DependencyProperty dp) at System.Windows.Data.BindingExpression.RefreshExpression() at System.Windows.Data.BindingExpression.SendDataToTarget() at System.Windows.Data.BindingExpression.SourceAquired() at System.Windows.Data.BindingExpression.DataContextChanged(Object o, DataContextChangedEventArgs e) at System.Windows.FrameworkElement.OnDataContextChanged(DataContextChangedEventArgs e) at System.Windows.FrameworkElement.OnTreeParentUpdated(DependencyObject newParent, Boolean bIsNewParentAlive) at System.Windows.DependencyObject.UpdateTreeParent(IManagedPeer oldParent, IManagedPeer newParent, Boolean bIsNewParentAlive, Boolean keepReferenceToParent) at MS.Internal.FrameworkCallbacks.ManagedPeerTreeUpdate(IntPtr oldParentElement, IntPtr parentElement, IntPtr childElement, Byte bIsParentAlive, Byte bKeepReferenceToParent)



从我通过在线查看收集到的信息来看,这通常意味着已经添加到可视化树中的可视化元素正在尝试再次添加。这种原因是因为如果我只显示 1 个插件并关闭它,它就会消失并且没有错误。我相当肯定该错误是由于 WorkspacePlugin.View 属性是一个可视控件,并且绑定(bind)更新正在尝试将其重新添加到可视树中。

我该如何解决这个问题或在没有错误消息的情况下达到预期的结果?

最佳答案

您可能不应该同时使用 Prism Region 和通过 ItemsSource 将 View 绑定(bind)到 ListView。通常人们会选择其中之一。我认为您可能会看到一些奇怪的行为,因为您两者都有。

我建议您的模块在其初始化方法中贡献“插件”。

public MyModule : IModule
{
IRegionManager _mgr;
public MyModule(IRegionManager mgr)
{
_mgr = mgr;
}

public void Initialize()
{
_mgr.RegisterViewWithRegion("Workspace", typeof(MyPlugin));
}

}

您应该可以在此之后的第二天调用它。您不必从您的外壳收集并提供一组插件到您想要显示它们的区域......您应该让您的模块自己将它们贡献给该区域。这将允许您保持一定程度的抽象,并让您的模块更加自主。

祝你好运。

关于c# - ItemsControl 中的 PRISM View 注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1917644/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com