多个ViewModel之间的WPF通信

时间:2018-11-15 10:00:34

标签: c# wpf xaml

我目前正在使用WPF应用程序,但有几个问题。到目前为止,我已经将所有业务逻辑放在一个ViewModel中,而我现在注意到的是ViewModel没有特定的上下文。

一个例子是:

        <telerik:RadSplitContainer Orientation="Vertical" telerik:DockingPanel.InitialSize="750,200">
            <telerik:RadPaneGroup IsContentPreserved="False" telerik:ProportionalStackPanel.RelativeSize="200,300" >
                <telerik:RadPane 
                        <ContentControl ContentTemplate="{StaticResource CategoryTemplate}"  
                                    Content="{Binding CategoryViewModel}" />
                </telerik:RadPane>
            </telerik:RadPaneGroup>
            <telerik:RadPaneGroup IsContentPreserved="False" telerik:ProportionalStackPanel.RelativeSize="100,120">
                <telerik:RadPane Header="Items list" 
                                 CanUserClose="False" CanUserPin="False"
                                 CanDockInDocumentHost="True">
                    <ContentControl ContentTemplate="{StaticResource ItemsListTemplate}"  
                                    Content="{Binding ItemsViewModel}" />
                </telerik:RadPane>
            </telerik:RadPaneGroup>
        </telerik:RadSplitContainer>

但是,这是mainwindows.xaml的样子,它是由指定为数据模板的多个视图构建的。此时,我决定从庞大的通用视图模型中提取业务逻辑,并为每个视图创建一个视图模型。

我有两种视图,一种用于类别,一种用于与类别相对应的项目。这两个视图包含一个gridview,该网格视图显示CategoryView中的类别以及与该类别相对应的项目。

包含所有项目的viewmodel最初为空,类别仅从DB中检索所有现有类别。在CategoryViewModel中也有一个SelectedCategory,其中包含我选择的网格行项目。

我想做的是在categoryView的网格中选择一行,我希望CategoryViewModel告诉ItemsViewModel检索与我从CategoryViewModel检索到的categoryID相对应的项。然后使用INotifyPropertychanged刷新itemsViewModel中的itemscollection,并刷新网格上的视图。

我的mainView视图和视图模型:

    public MainViewModel()
    {
        this.InitializeCommands();
        this.ItemsViewModel = new ItemsViewModel();
        this.CategoryViewModel = new CategoryViewModel();

    }

    public ViewModelBase CategoryViewModel
    {
        get { return this._categoryViewModel; }
        set
        {
            if (this._categoryViewModel != value)
            {
                this._categoryViewModel = value;
            }
        }
    }

    public ViewModelBase ItemsViewModel
    {
        get
        {
            if (this._itemsViewModel == null)
            {
                this._itemsViewModel;
            }
            return this._itemsViewModel;
        }
        set
        {
            if (this._itemsViewModel != value)
            {
                this._itemsViewModel = value;
            }
        }
    }

MainView中使用的另一个视图数据模板的示例:

<DataTemplate x:Key="NewsTemplate">
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
                   <telerik:RadBusyIndicator x:Name="BusyIndicator">
            <telerik:RadGridView Name="gridView"
                                                 ItemsSource="{Binding 
         Category}"
                                                 SelectedItem="{Binding SelectedCategory, Mode=TwoWay}">   
                <telerik:RadGridView.Columns>
                    <telerik:GridViewDataColumn DataMemberBinding={Binding Name}" Header="Name"/>     
            </telerik:RadGridView>
        </telerik:RadBusyIndicator>
    </Grid>
</DataTemplate>`

为项目添加了视图模型:

    public ObservableCollection<Item> GetItems
    {
        get
        {
            this._getItems = GetFromDb.GetItems(CategoryID)

            return this._getItems;
        }
        set
        {
            if (this._getItems != value)
            {
                this._getItems = value;
                this.OnPropertyChanged("GetItems");
            }
        }
    }

    public QueryableCollectionView Items
    {
        get
        {
            return this._items = new QueryableCollectionView(GetItems(CategoryID));
        }
        set
        {
            if (this._items != value)
            {
                this._items = value;
                this.OnPropertyChanged(() => Items);
            }
        }
    }

MainViewModel(如果您查看的话,我有一个方法GetFromDb.GetItems(CategoryID)来检索项目):

    public MainViewModel()
    {
        this.InitializeCommands();          
        this.CategoryViewModel = new CategoryViewModel();
        this.ItemsViewModel = new ItemsViewModel();

        this.CategoryViewModel.OnChanged += (s, e) => {

            //this one?
            this.ItemsViewModel.ContractMetaDatas(CategoryViewModel.ID)
            //this one?
            this.ItemsViewModel.ContractMetaDatas = new QueryableCollectionView(GetFromDb.GetItems(CategoryID));
        };
    }

我该如何实现?

1 个答案:

答案 0 :(得分:0)

  

我想做的是在categoryView的网格中选择一行,我希望CategoryViewModel告诉ItemsViewModel检索与我从CategoryViewModel检索到的categoryID相对应的项。然后使用INotifyPropertychanged刷新itemsViewModel中的itemscollection,并刷新网格上的视图。

     

我该如何实现?

好吧,基本上,您可以对事件使用典型的设置:

从您的CategoryViewModel中触发一个事件,并在整个容器中进行处理。

 public class MainViewModel: INotifyPropertyChanged
 {
     public CategoryViewModel CategoryViewModel {get;set;}
     public ItemsViewModel ItemsViewModel {get;set;}

     public MainViewModel()
     {   
         this.InitializeCommands();
         this.ItemsViewModel = new ItemsViewModel();
         this.CategoryViewModel = new CategoryViewModel();
         //wire up the event 
         this.CategoryViewModel.OnChanged += (s,e) => {
            //perform update here
            this.ItemsViewModel.UpdateWithId(this.CategoryViewModel.SelectedId);
        };
     }

    ///...
 }

类别:

public class CategoryViewModel : INotifyPropertyChanged
{
    //fire this when appropiate
    public event EventHandler OnChanged;
    ///...
}