簡體   English   中英

MVVM - 如何從父 ViewModel 引用子 ViewModel(ViewModel 在其視圖中創建)?

[英]MVVM - How can I refer to child ViewModel from parent ViewModel (ViewModels are created in their Views)?

如果我使用 Views 創建 ViewModel 實例且 ViewModel 沒有對 View 的引用的方法,我不知道創建 viewmodel 關系的正確方法是什么。

假設我們有 ChildView 控件,它創建了一個具有 SaveCommand 的 ViewModel 實例。

<UserControl x:Class="App.ChildView" ...>
    <UserControl.DataContext>
        <local:ChildViewModel/>
    </UserControl.DataContext>
    <!-- some controls -->
</UserControl>

public class ChildViewModel
{
    public RelayCommand SaveCommand { get; set; }
    public ChildViewModel()
    {
        SaveCommand = new RelayCommand(SaveExecute);
    }
    private void SaveExecute()
    {
         Debug.WriteLine("Child data has been saved.");
    }
}

現在,我將兩個控件放在父視圖中,並希望對所有子視圖執行 SaveCommand。

<Window x:Class="App.ParentView" ...>
    <Window.DataContext>
        <local:ParentViewModel/>
    </Window.DataContext>
    <Grid>
        <local:ChildView x:Name="child1"/>
        <local:ChildView x:Name="child2"/>
        <Button Content="Save All" Command="{Binding ParentSaveCommand}">
    <Grid/>
</Window>

public class ParentViewModel
{
    public RelayCommand ParentSaveCommand { get; set; }
    public ParentViewModel()
    {
        ParentSaveCommand = new RelayCommand(ParentSaveExecute);
    }
    private void ParentSaveExecute()
    {
        Debug.WriteLine("Saving all has started...");

        // <childVM1>.SaveCommand.Execute();
        // <childVM2>.SaveCommand.Execute();

        // From where should I get ChildViewModel?
    }
}

我應該如何正確地引用孩子的 ViewModel?

我找到了可能的解決方案:

  • 向返回孩子的 ViewModel 的 ParentView 添加一個接口(就像 AngelSix 使用密碼所做的那樣
  • 創建一個能夠將 ChildView.DataContext 綁定到 ParentView.DataContext.Child1ViewModel 屬性的 class。

.

或者也許這是錯誤的方法,ParentViewModel 應該創建一個 ChildViewModel 實例,而 ParentView 應該為 child1 和 child2 設置 DataContext (當然是通過綁定)?

就像提到的 RTF 一樣,對於這些類型的操作,讓父虛擬機創建子虛擬機通常是一種更簡單的方法,這樣父虛擬機就可以維護對子虛擬機的引用。 但是,您絕對可以在不改變架構的情況下做您想做的事。

在視圖中:

 <Button
  Content="Save All"
  Height="37" Command="{Binding SaveAllCommand}">
       <Button.CommandParameter>
            <MultiBinding Converter="{StaticResource PassThroughConverter }">
                  <Binding Path=“DataContext” ElementName="child1"/>
                  <Binding Path=“DataContext” ElementName="child2"/>
            </MultiBinding>
       </Button.CommandParameter>
 </Button>

轉換器:

public class PassThroughConverter : IMultiValueConverter
{
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            return values.ToList();
        }
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }

在父視圖 model 中:

public class ParentViewModel
{
    public RelayCommand<object> ParentSaveCommand { get; set; }
    public ParentViewModel()
    {
        this.ParentSaveCommand = new RelayCommand<object>(obj => this.ParentSaveExecute(obj));
    }
    private void ParentSaveExecute(object items)
    {
        foreach (var item in (ChildViewModel[])items)
        {
            item.SaveCommand.Execute();
        }
    }
}

我通常總是在后面的代碼中分配 DataContext,這樣我就可以注入依賴項來查看 model 構造函數。 我的方法是通過構造函數將父視圖 model 傳遞給子視圖模型。 如果你有我會在父視圖 model 中創建一個 SaveAll 事件並讓子視圖模型訂閱它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM