DataContext用于在DataTemplate中将UserControl与ViewModel绑定

时间:2011-09-20 20:02:26

标签: wpf data-binding mvvm

我想要实现的目标是:

  • 将ListView绑定到ItemRecords的ObservableCollection。
  • 有一个TabControl,其中包含ListView中所有选择进行编辑的ItemRecords的详细视图。
  • 每个TabItem都包含一个UserControl(“ItemInfo”),它使用ItemInfoViewModel作为其VM(并且,并非巧合的是,DataContext)。
  • ItemInfo UserControl需要使用相应ItemRecord中的数据填充。

为实现这一点,我正在尝试将ItemRecord(在ListView中选择)传递给ItemInfoViewModel。

最后,问题:在不打破MVVM模式的情况下,您认为最好的方法是什么?

我看到的不那么优雅的方式(实际上并不完全遵循MVVM原则)是在UserControl中定义DependencyProperty ItemRecord,通过绑定提供其值,并在构造函数中(在UserControl的代码隐藏)将ItemRecord传递给VM(我们通过转换DataContext获得)。

另一个问题是如何通过绑定实际传递ItemRecord。 一旦我将VM设置为UserControl的DataContext,我就不能只使用{Binding}来指定TabControl的源集合中的当前项。 目前我使用ElementName绑定到TabControl的SelectedItem - 但这听起来不太健壮: - (

<localControls:TabControl.ContentTemplate>
    <DataTemplate>
        <ScrollViewer>
            <localControls:ItemInfo ItemRecord="{Binding ElementName=Tabs, Path=SelectedItem}"/>
        </ScrollViewer>
    </DataTemplate>
</localControls:TabControl.ContentTemplate>

非常感谢任何好的建议!

Alex

1 个答案:

答案 0 :(得分:1)

我认为你的问题是你在这里不太了解MVVM模式;你仍然把这看作是与对方交谈的不同控件。在MVVM中,它们不应该是,每个控件都与视图模型独立地与所有其他控件进行通信。视图模型控制(并提供)告诉控件如何表现的逻辑。

所以,理想情况下你会有类似的东西:

public ObservableCollection<ItemRecord> ListViewRecords 
{
   get { ... }
   set { ... }
}

public IEnumerable<ItemRecord> SelectedListViewRecords {
{
   get { ... }
   set { ... }
}

ListViewRecords将绑定到ItemsSource的{​​{1}}属性(实际属性可能因您使用的特定控件而异,我已经习惯了Telerik此刻的套房让我的脑袋在哪里)。 ListView将绑定到SelectedListViewRecords的{​​{1}}属性。那么对于你的TabControl,你会得到:

SelectedItems

同样,您可以将ListView属性绑定到public ObservableCollection<MyTabItem> Tabs { get { ... } set { ... } } public MyTabItem SelectedTab { get { ... } set { ... } } ,将Items绑定到Tabs上的SelectedItem。现在您的视图模型包含所有逻辑,因此在您的SelectedTab中,您可能会执行以下操作:

TabControl

所以这里的想法是控件只是发送和接收属性更改,它们对底层数据,逻辑等一无所知。它们只是显示它们的绑定属性告诉它们显示的内容。