WPF UserControl 多个DataContexts?

问题描述

我目前有一个带有 TreeView 和其他一些东西的用户控件。 TreeView 的 DataContext 设置为 viewmodel 并且绑定有效:

<TreeView Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"
          ItemsSource="{Binding LoadedItem.Batches}" 
          Background="{Binding UiTools.ContainersBackground}">
  <Interactivity:Interaction.Behaviors>
    <Behaviros:BindableSelectedItemBehavior SelectedItem="{Binding SelectedSessionItem,Mode=TwoWay}"/>
  </Interactivity:Interaction.Behaviors>
  <TreeView.ItemContainerStyle>
    <Style targettype="{x:Type TreeViewItem}">
      <Setter Property="IsExpanded" Value="True"/>
    </Style>
  </TreeView.ItemContainerStyle>
  <TreeView.ItemTemplate>
    <HierarchicalDataTemplate ItemsSource="{Binding Groups}">
      <TextBlock Text="{Binding Name,UpdateSourceTrigger=LostFocus}"/>
      <HierarchicalDataTemplate.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Samples}">
          <TextBox Text="{Binding Name}"/>
          <HierarchicalDataTemplate.ItemTemplate>
            <HierarchicalDataTemplate>
              <TextBlock Text="{Binding Name}"/>
            </HierarchicalDataTemplate>
          </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
      </HierarchicalDataTemplate.ItemTemplate>
    </HierarchicalDataTemplate>
  </TreeView.ItemTemplate>
</TreeView>

但现在我正在尝试使用 this 教程使节点可编辑。

在那里,UserControl 使用了一些隐藏的代码,现在它实现了 INotifyPropertyChanged。事件处理程序的定义很简单:

    public event PropertyChangedEventHandler PropertyChanged;

但是使用的时候总是null

public bool IsInEditMode
{
  get { return isInEditMode; }
  set
  {
    isInEditMode = value;
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
      handler(this,new PropertyChangedEventArgs(nameof(IsInEditMode)));
    }
  }
}

在这里,处理程序永远不会被调用,因为它总是空的。

我想这是因为我的 UserControl 的 DataContext 设置为 viewmodel 而不是 UserControl 本身。

当我将 DataContext 设置为 UserControl 时,我将无法将数据绑定到 viewmodels 项。

如何解决这个问题?

解决方法

视图上的每个控件都有自己的 DataContext。默认情况下,它只会继承父 DataContext,但您可以将其显式设置为您想要使用的任何内容:

DataContext={whatever}

或者,在这种情况下更常见的是,您可以使用 ElementName 在绑定本身中指定不同的绑定源。请注意您提到的教程中的绑定:

<Condition Binding="{Binding IsInEditMode,ElementName=wpfTreeViewInPlaceEditControl}" Value="True"/>

ElementName 位表示查看指定元素 (wpfTreeViewInPlaceEditControl) 而不是绑定源的当前 DataContext。

,

事件处理程序为空,因为没有附加委托。
显然,您对此属性的绑定无法解析。

通常,您可以绑定到每个源(必须满足某些限制,例如作为公共属性),而不仅限于 DataContext

您可以指定 Binding.ElementName 将绑定源设置为命名元素或使用 Binding.RelativeSource 遍历可视化树以查找源对象。

在您的情况下,您可以使用 Binding.RelativeSource 来查找 UserControl

{Binding RelativeSource={RelativeSource AncestorType UserControl},Path=IsInEditMode}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...