如何将数据导入UserControl的ViewModel?

时间:2012-03-24 16:28:55

标签: wpf mvvm user-controls viewmodel

WPF / MVVM新手。我有一个类型为“MyData”的数据对象。其中一个属性是“MySubsetData”类型。

我在数据网格中显示“MyData”对象的集合。

<DataGrid ItemsSource="{Binding Path=MyDataCollection}">
    <!-- Each row of the datagrid contains an item of type "MyData" -->
    <DataGrid.Columns .../>
    <DataGrid.RowDetailsTemplate>
        <DataTemplate>
            <local:MySubsetDataUserControl/>
        </DataTemplate>
    </DataGrid.RowDetailsTemplate>
</DataGrid>

行详细信息应显示“MySubsetData”的内容。行详细信息的视图位于单独的用户控件中(此处:“MySubsetDataUserControl”)。

目前我没有为“MySubsetDataUserControl”设置视图模型,所以它从父的datagrid行继承了数据上下文。

<UserControl>
    <!-- Namespace stuff not shown for simplicity -->
    <Grid DataContext="{Binding Path=MySubsetData}">
        <!-- Show the MySubsetData properties here -->
        <!-- e.g. a textbox -->
            <TextBox Text="{Binding Path=TextData, UpdateSourceTrigger=PropertyChanged}"/>
    </Grid>
</UserControl>

尽管这很有效,但我遇到了这种方法的几个问题:

  1. 所有业务逻辑都将位于用户控件父视图模型中,它根本不属于该模型。使视图模型比它需要的更加混乱。更不用说用户控件xaml中的命令绑定看起来也很丑陋。感觉不对劲。

  2. 由于可以同时显示更多行详细信息,因此无法将“MySubsetData”的属性绑定到视图模型中的可观察属性。即如果我更改代码中的属性(例如TextData),则更改将不会反映在视图中。我的解决方法是不改变属性“TextData”。相反,我更改了文本框Text属性的内容,而后者又会更新“TextData”属性。这感觉非常错误!

  3. 所以我想为我的用户控件使用另一个视图模型,但我不知道如何访问我的数据。

    <UserControl.DataContext>
        <local:UserControlViewModel/>
    </UserControl.DataContext>
    

    如何立即访问“MySubsetData”?

1 个答案:

答案 0 :(得分:0)

假设你有一个这样的视图模型:

public class ViewModel
{
    public IEnumerable<MyData> MyDataCollection{get; private set;}
}

哪里

public class MyData
{
    public MySubsetData MySubsetData { get; }
}

包含DataGrid的视图将是

<UserControl.DataContext>
    <local:ViewModel>
</UserControl.DataContext>

<DataGrid ItemsSource="{Binding Path=MyDataCollection}">
    <DataGrid.Columns .../>
    <DataGrid.RowDetailsTemplate>
        <DataTemplate> 
            <!-- each row of the items control has an implicit DataContext of MyData -->
            <!-- so bind the DataContext of the subset control to MySubsetData -->
            <local:MySubsetDataUserControl DataContext={Binding MySubsetData}/>
        </DataTemplate>
    </DataGrid.RowDetailsTemplate>
</DataGrid>

现在您的子集控件看起来像

<UserControl>
    <Grid>
        <TextBox Text="{Binding Path=TextData, UpdateSourceTrigger=PropertyChanged}"/>
    </Grid>
</UserControl>

重新阅读这个问题,也许我所做的就是以稍微不同的方式重复问题中的Xaml。

然而,各种类应该实现INotifyPropertyChanged,例如

public class MySubsetData : INotifyPropertyChanged
{
   public string TextData
   {
      get{...}
      set{...; OnPropertyChanged("TextData"); }
   }
}

然后绑定到TextData属性的TextBox将反映代码中所做的更改。