• 在Prism 框架中,实现主程序与模块间 UI 的通信


    背景:

       在模块的UI中包含 TreeView 控件,在该树形控件的每一节点前面定义了一个复选框,如图

    需求:

       在两个不同的应用程序中使用该控件,而它在不同应用程序中的外观则并不一致,按照本例,即一个显示复选框,一个不显示。

    问题:

        解决该问题的一个难处在于,Prism框架本身的设计原则——此 View 会被添加到主程序的 Shell 的 Region 中,所以在主程序中不能直接来控制该 View 的属性及其逻辑。

    思路:

       利用 EventAggregator 使得主程序与模块间进行通信,从而间接地达到我们的目的。

    实现:

       首先,在模块的 View 所对应的 ViewModel 中添加一个属性 ShowCheckbox,如下:

            public bool ShowCheckbox
            {
                get { return this.showCheckBox; }
                set { this.SetProperty(ref this.showCheckBox, value); }
            }

       其中的 SetProperty 方法是在 BindableBase 类(由 Prism.MVVM 库提供)的方法,其介绍可点击这里,这样写的好处:1. 省去自己再实现 INotifyPropertyChanged 接口;2. 避免可能在类似 RaisePropertyChanged("XXX") 语句中写错属性的名字。只要当我们的 ViewModel 类继承了 BindableBase 类,就可以这样来定义那些值被更改后需要通知UI的属性。

       并在 View 中为其添加绑定,如下 CheckBox 的 Visibility 属性的绑定:

        <UserControl.Resources>
            <HierarchicalDataTemplate x:Key="HierarchicalView" ItemsSource="{Binding SubCategories}">
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
                    <CheckBox IsChecked="{Binding IsChecked}" Margin="6,6,5,0" Visibility="{Binding ShowCheckbox,ElementName=treeViewControl,Converter={StaticResource BoolToVisibilityConverter}}" />
                    <TextBlock Text="{Binding Name}" FontSize="20" />
                    <StackPanel.ToolTip>
                        <TextBlock VerticalAlignment="Center" Text="{Binding Name}" TextWrapping="Wrap" MaxWidth="200" />
                    </StackPanel.ToolTip>
                </StackPanel>
            </HierarchicalDataTemplate>
    </UserControl.Resources>

        然后,我们需要在底层库 Infrastructure 中定义一个事件,主程序与模块就是通过该事件来进行通信,以达到修改模块中 UI 的值,代码如下:

        public class ControlVisibleEvent : PubSubEvent<bool>
        {
        }

       接下来,就是对该事件进行订阅与发布,自然地,我们在模块中来订阅上述事件,代码如下:

    this.EventAggregator.GetEvent<DemoBase.ControlVisibleEvent>().Subscribe((value) =>
                {
                    this.ShowCheckbox = value;
                });

       在订阅事件时,我们获取值并把获取到的值传给  ViewModel 的 ShowCheckbox 属性,再通过WPF的通知机制以达到UI的变化。

       在主程序中,我们发布该事件,发布时,需要考虑的问题是在何时发布,这里我们选择在加载模块完成的事件中进行发布,代码如下(注意其中的高亮代码):

            public MainWindow(IEventAggregator eventAggregator, IModuleManager moduleManager)
            {
                InitializeComponent();
                this.EventAggregator = eventAggregator;
                this.ModuleManager.LoadModuleCompleted += ModuleManager_LoadModuleCompleted;
            }
    
            void ModuleManager_LoadModuleCompleted(object sender, LoadModuleCompletedEventArgs e)      {       
    this.EventAggregator.GetEvent<DemoBase.ControlVisibleEvent>().Publish(false);
            }

       这时,在不同的应用程序中,只要修改在发布事件时的值,即可达到模块中UI的改变。

    备注:

       实现此需求的不止上述方法,此外,利用 Region 对象的 RegionContext 属性也是一种不错的办法,后续可以再进行研究。

    作者:WPInfo

    本文系作者原创,欢迎转载;如需转载,请注明出处。

    公众号:.NET之窗 (WinDotNET),更多原创、优质技术文章,欢迎扫码关注。

  • 相关阅读:
    js笔记1
    106. Construct Binary Tree from Inorder and Postorder Traversal根据后中序数组恢复出原来的树
    365. Water and Jug Problem量杯灌水问题
    452. Minimum Number of Arrows to Burst Balloons扎气球的个数最少
    650. 2 Keys Keyboard复制粘贴的次数
    249. Group Shifted Strings把迁移后相同的字符串集合起来
    450. Delete Node in a BST 删除bst中的一个节点
    528. Random Pick with Weight index的随机发生器
    582. Kill Process杀死所有子代
    348. Design Tic-Tac-Toe设计井字游戏
  • 原文地址:https://www.cnblogs.com/wpinfo/p/4642829.html
Copyright © 2020-2023  润新知