phibel
phibel

Reputation: 171

WPF UserControl multiple DataContexts?

I currently have an usercontrol with a TreeView and some other things. The TreeView's DataContext is set to the ViewModel and the binding works:

<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>

But now I'm trying to make the nodes editable using this tutorial.

There, for the UserControl some code behind is used, and it now implements INotifyPropertyChanged. The event handler simply is defined:

    public event PropertyChangedEventHandler PropertyChanged;

But when it is used, it is always null:

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

Here, handler is never called, 'cause it is always null.

I suppose it is because the DataContext of my UserControl is set to the ViewModel and not to the UserControl itself.

When I'd set the DataContext to the UserControl I would not be able to data bind to the ViewModels items.

How could this be solved?

Upvotes: 1

Views: 411

Answers (2)

BionicCode
BionicCode

Reputation: 28968

The event handler is null, because there is no delegate attached.
Obviously your binding to this property does not resolve.

Generally, you can bind to every source (that has to meet certain constraints e.g. being a public property), not only to the DataContext.

You can specify Binding.ElementName to set the binding source to a named element or use Binding.RelativeSource to traverse the visual tree to find a source object.

In your case you can use Binding.RelativeSource to find the UserControl:

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

Upvotes: 1

GazTheDestroyer
GazTheDestroyer

Reputation: 21251

Every control on the view has its own DataContext. It will just inherit the parent DataContext by default, but you can explicitly set it to whatever you want using:

DataContext={whatever}

Alternatively, and more usual in these kind of situations, you can specify a different binding source within the binding itself using ElementName. Note the binding in the tutorial you mention:

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

The ElementName bit says to look at the specified element (wpfTreeViewInPlaceEditControl) rather than the current DataContext for the binding source.

Upvotes: 2

Related Questions