代码之家  ›  专栏  ›  技术社区  ›  Tom

棱镜视图内部项目注入控件

  •  1
  • Tom  · 技术社区  · 16 年前

    更新(12/17/2009): 现在反映了我取得的最新进展。

    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);
            }
    
        }
    

    <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>
    

    注意绑定到WorkspacePlugin的“View”属性的内容控件,以及绑定了Click.Command和“CloseCommand”的按钮。

    现在的问题

    System.ArgumentException:值不在预期范围内。 在MS.Internal.XcpImports.CheckHResult(UInt32小时) 位于MS.Internal.XcpImports.SetValue(INativeCoreTypeWrapper对象,DependencyProperty属性,DependencyObject doh) 位于System.Windows.DependencyObject.RefreshExpression(DependencyProperty dp) 位于System.Windows.Data.BindingExpression.RefreshExpression()处 位于System.Windows.Data.BindingExpression.SourceAquired()处 在System.Windows.FrameworkElement.OnTreeParentUpdated(DependencyObject newParent,Boolean bIsNewParentAlive) 位于System.Windows.DependencyObject.UpdateTreeParent(IManagedPeer oldParent、IManagedPeer newParent、Boolean bIsNewParentAlive、Boolean keepReferenceToParent)

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

    2 回复  |  直到 16 年前
        1
  •  0
  •   Anderson Imes    16 年前

    您可能不应该同时使用棱柱区域和通过ItemsSource将视图绑定到ListView。通常人们会选择其中一个。我想你可能会看到一些奇怪的行为,因为你两者都有。

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

    public MyModule : IModule
    {
         IRegionManager _mgr;
         public MyModule(IRegionManager mgr)
         {
              _mgr = mgr;
         }
    
         public void Initialize()
         {
              _mgr.RegisterViewWithRegion("Workspace", typeof(MyPlugin));
         }
    
    }
    

    你应该可以在这之后的一天打电话。你不应该收集和提供一个从你的外壳到你想要展示它们的区域的插件集合。。。您应该让您的模块将它们贡献给区域本身。这将允许您保持一定量的抽象,并使您的模块更加自治。

    祝你好运

        2
  •  0
  •   Tom    16 年前

    我创建了一个WorkspaceItemView视图和ViewModel,大致如下所示:

    <UserControl>
    <Grid  x:Name="ResizeGrid"
           MouseEnter="Plugin_MouseEnter"
           MouseLeave="Plugin_MouseLeave">
        <Grid.RowDefinitions>
            <RowDefinition Height="20" />
            <RowDefinition Height="*" />
            <RowDefinition Height="5" />
        </Grid.RowDefinitions>
    
        <Border x:Name="border"
                BorderBrush="Black"
                BorderThickness="2"
                Padding="0"
                Margin="-1,-1,-1,-1">
        </Border>
    
        <Grid x:Name="grid"
              Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width=".05*" />
            </Grid.ColumnDefinitions>
            <Thumb HorizontalAlignment="Stretch"
                   Background="Green"
                   DragDelta="Thumb_DragDelta"
                   />
            <Button Content="X"
                    HorizontalAlignment="Right"
                    Grid.Column="1"
                    cmd:Click.Command="{Binding CloseCommand}"
                    cmd:Click.CommandParameter="{Binding PluginID}" />
        </Grid>
    
        <Border BorderBrush="Black"
                BorderThickness="2"
                Margin="0"
                VerticalAlignment="Center"
                HorizontalAlignment="Center"
                Grid.Row="1">
            <tk:Viewbox Stretch="Uniform"
                        StretchDirection="Both">
                <ContentControl rgn:RegionManager.RegionName="PluginViewRegion" />
    
            </tk:Viewbox>
        </Border>
        <Thumb x:Name="SizeGrip"
               Grid.Row="1"
               VerticalAlignment="Bottom"
               HorizontalAlignment="Right"
               Width="10"
               Height="10"
               Margin="0,0,-7,-7"
               Style="{StaticResource SizeGrip}"
               DragDelta="SizeGrip_DragDelta"
               DragStarted="SizeGrip_DragStarted"
               DragCompleted="SizeGrip_DragCompleted" />
    
    </Grid>
    </UserControl>  
    

    public class WorkspaceItemViewModel : INotifyPropertyChanged
    {
        private IWorkspaceManager workspaceManager;
        private IRegionManager regionManager;
        private Guid pluginID;
    
        public WorkspaceItemViewModel(IWorkspaceManager workspaceManager, IRegionManager regionManager)
        {
            this.workspaceManager = workspaceManager;
            this.regionManager = regionManager;
        }
    
        public DelegateCommand<object> CloseCommand 
        {
            get
            {
                return workspaceManager.CloseCommand;
            }    
        }
    
        public DelegateCommand<object> SelectCommand
        {
            get
            {
                return workspaceManager.SelectCommand;
            }
        }
    
        public object CloseCommandParameter
        {
            get
            {
                return this;
            }
        }
    
        public Guid PluginID
        {
            get
            {
                return this.pluginID;
            }
            set
            {
                this.pluginID = value;
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs("PluginID"));
                }
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    

    }

    public void AddPluginToWorkspace(string pluginName)
        {
            PluginInfo pi = AvailablePlugins[pluginName];
            WorkspacePlugin wsp = new WorkspacePlugin();
            wsp.Name = pi.Name;
            wsp.CloseCommand = new DelegateCommand<object>(this.PluginClosing);
            wsp.SelectCommand = new DelegateCommand<object>(this.PluginSelected);
            wsp.id = System.Guid.NewGuid();
            this.modules.Add(wsp.id, wsp);
    
            var view = this.unityContainer.Resolve(pluginWindowType);
            if (view is IWorkspacePlugin)
            {
                var iwsp = view as IWorkspacePlugin;
                if (iwsp != null)
                {
                    iwsp.PluginID = wsp.id;
                }
            }
            else
            {
                throw new ArgumentException("Plugin view containers must implement IWorkspacePlugin.");
            }
    
            var workspaceRegion = regionManager.Regions["Workspace"];
            var pluginRegion = workspaceRegion.Add(view, wsp.id.ToString(), true);
            this.unityContainer.RegisterInstance<IRegionManager>(wsp.id.ToString(), pluginRegion);
            pluginRegion.Regions["PluginViewRegion"].Context = view;
            pluginRegion.Regions["PluginViewRegion"].Add(this.unityContainer.Resolve(pi.ViewType));
    
            this.eventAggregator.GetEvent<ActivePluginsChanged>().Publish(wsp);
    

    这实际上是创建一个范围区域,将WorkspaceItemView添加到工作区区域,然后解析实际插件的视图并将其添加到新添加的WorkspaceItemView的PluginViewRegion。我有一点清理工作要做,但我觉得效果不错。

    谢谢你的帮助。