WPF UserControl 多个数据上下文?

WPF UserControl multiple 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。

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

通常,您可以绑定到每个来源(必须满足某些限制,例如 public 属性),而不仅仅是 DataContext.

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

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

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