在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 屬性也是一種不錯的辦法,后續可以再進行研究。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM