question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Bindings with RalativeSource of type FindAncestor are not re-evaluated when an element moves in the visual tree

See original GitHub issue
  • .NET Core Version: 5.0.102
  • Windows version: 10.0.19042.746
  • Does the bug reproduce also in WPF for .NET Framework 4.8?: Yes

Problem description: When an element containing a binding with relative source FindAncestor is moved in the visual tree, the binding is not re-evaluated.

Expected behavior: The binding to be re-evaluated and determine the new/current relative-source ancestor.

Minimal repro: Create a WPF app that somehow hosts the following elements. For readability, layout properties have been removed.

<DockPanel>
    <ContentPresenter x:Name="Parent1">
        <ContentPresenter.Content>
            <Border Background="{Binding Path=BorderBrush, RelativeSource={RelativeSource AncestorType={x:Type Border}}}" />
        </ContentPresenter.Content>
    </ContentPresenter>
</DockPanel>
<Border BorderBrush="Red">
    <ContentPresenter x:Name="Parent2"  />
</Border>
<Border BorderBrush="Blue">
    <ContentPresenter x:Name="Parent3"  />
</Border>

Create a button or similar logic that moves the content in the visual tree. Example:

object content = this.Parent1.Content;
this.Parent1.Content = null;
this.Parent2.Content = content;

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:5
  • Comments:6

github_iconTop GitHub Comments

1reaction
DSPaulcommented, Nov 28, 2022

I managed to fixed the issue in my case by setting x:Shared=“false” which I just learned about. The bug is still a problem, but creating a new instance rather than re-evaluating just happens to be a valid workaround in my case, but can only be applied when the object in question is in a resource dictionary which is not the case for the original issue.

0reactions
DSPaulcommented, Jul 19, 2022

This issue persists in .NET core, I am using .NET 6.0 and running into the same problems. In my case, I have data that can be displayed using different layouts. These layouts are UserControls that are displayed in a ContentControl and switched between using a DataTemplate.

<DataTemplate DataType="{x:Type viewmodels:ListLayoutViewModel}">
    <views:ListLayout DataContext="{Binding}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewmodels:TileLayoutViewModel}">
    <views:TileLayout DataContext="{Binding}"/>
</DataTemplate>
<ContentControl Content="{Binding CurrentLayout}"/>

I have a ContextMenu for when multiple items are selected, and would like that same contextmenu in every layout, because the layout is just UI fluff, the functionality between them should be the same. I need to bind the CommandParameter to the SelectedItems of either a DataGrid or a Listbox, depending on the layout and do stuff with those items such as deleting them as shown in this example.

<ContextMenu x:Key="MultiSelectContextMenu">
   <MenuItem Header="Delete All" 
      CommandParameter="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Selector}}}"
      Command="{Binding Path=DataContext.DeleteAllCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>
</ContextMenu>

When I put this ContextMenu in a resource.xaml file however, the CommandParameter binds to the SelectedItems of the first layout I right click on . When I change the layout and select different Items, the actions will still be performed on the selected items of the datagrid/listbox that is no longer there. It has not realised that the Ancestor has changed. As a sidenote, the binding of the command is also stale but that isn’t an issue as the command is the same for every layout, and inherited from a common LayoutViewModel.

The current workaround is to copy-paste the Context Menu as a resource into every layout so that it gets reinitialised when a new layout it loaded causing it to reevaluate the relative source which is a huge amount of code duplication. I really hope this issue gets looked at a second time and that this more real world example gives some context to where this would be useful in a real application.

And before you suggest to bind SelectedItems to a Property in the Viewmodel and access it that way as a workaround, that doesn’t work because of issue #3140.

Read more comments on GitHub >

github_iconTop Results From Across the Web

WPF Binding with RelativeSource and AncestorType
Therefore, the RelativeSource AncestorType binding does not yield any result. This should be indicated by a warning in your output window.
Read more >
Xamarin.Forms Relative Bindings
FindAncestor indicates the ancestor in the visual tree of the bound element. This mode should be used to bind to an ancestor control ......
Read more >
Can't find the right ancestor to bind to in UI for WPF
Data Error : 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.
Read more >
NoesisGUI 2.1 Changelog - Documentation
Fixed Crash in binding with RelativeSource FindAncestor when type was not resolved. Fixed Popup Closed event was raised twice for ContextMenu. Fixed Some ......
Read more >
Binding ContentPane's Header to a Property in ...
Hello,. we have a problem with the headertemplate of the contentpane in a DockManager. I've tried several binding paths and ancestortypes.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found