Bindings Don't Work within Flyout within ControlTemplate
See original GitHub issueDescribe the bug
While writing the ColorPicker it was discovered that TemplateBinding was not working in the control template. Even switching to a standard Binding with RelativeSource set to TemplatedParent doesn’t seem to work.
~This issue appears to be because the Flyout, once opened, is not added to the logical tree (@maxkatz6 pointed this out and ran across a similar issue with the SplitView).~
There are two issues here:
- The binding is not properly created with a TemplateBinding or Binding with RelativeSource=TemplatedParent. The parent is never set and/or the binding contexts are invalid.
- Working-around this issue with
Binding $parent[control].propertysyntax reveals another issue. When the Flyout is closed and destroyed, that triggers a binding update with the default/empty values back to the parent (for TwoWay bindings). This means whatever changes done when the Flyout is open are immediately lost when the Flyout closes. If issue 1 is fixed, this issue will still likely persist.
Both of these were not an issue in WPF/UWP.
To Reproduce
It is best just to test this in the ColorPicker PR #8215
<ControlTemplate>
<DropDownButton CornerRadius="{TemplateBinding CornerRadius}"
Height="{TemplateBinding Height}"
Width="{TemplateBinding Width}"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
Padding="0,0,10,0"
UseLayoutRounding="False">
<DropDownButton.Styles>
<Style Selector="FlyoutPresenter.NoPadding">
<Setter Property="Padding" Value="0" />
</Style>
</DropDownButton.Styles>
<DropDownButton.Flyout>
<Flyout FlyoutPresenterClasses="NoPadding">
<ColorView x:Name="FlyoutColorView"
Color="{Binding Color, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
ColorModel="{Binding ColorModel, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" />
</Flyout>
</DropDownButton.Flyout>
</DropDownButton>
</ControlTemplate>
Expected behavior
TemplateBinding should work within a Flyout just like UWP.
Screenshots
N/A
Desktop (please complete the following information):
- Windows 10 Pro
- Current master as of this writing
Additional context
- This might be an issue with the Flyout or with Button (which DropDownButton derives from)
- A partial work-around is to use
Binding $parent[control].propertysyntax
Issue Analytics
- State:
- Created a year ago
- Comments:9 (9 by maintainers)
Top Results From Across the Web
UWP Derived Button With Flyout: Binding within the Style
It seems that the only way for the flyout content to obtain information from it's attached element is through DataContext inheritance. I could ......
Read more >WPF FlyoutControl - Cannot focus control within flyout from ...
I have a DataTemplate which contains a TextEdit. The DataTemplate is bound to the ContentTemplate property of a Style for the DevExpress ...
Read more >TemplateBinding markup extension - UWP applications
Attempting to use a TemplateBinding outside of a ControlTemplate definition in XAML will result in a parser error. You can use TemplateBinding ...
Read more >Wpf context menu. PlacementTarget = rectangle; contextMenu ...
I've read that the ContextMenu is not under the main Visual tree so i can't bind it directly, but any method i try...
Read more >Xamarin.Forms 5: Dual Screens, Dark Modes, Designing ...
You just need to assign a custom template to the control's template property; described in C# or XAML, it doesn't matter. Supplying a...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found

TemplatedParent is applied only on these logical children which were in the tree at a time, when template was applied. Which makes sense.
And while Flyout’s content and ToolTip are part of the logical tree as they should. The problem is they both are added to the logical tree only after being opened. I.e., after template was created. For popups it was solved like forever ago https://github.com/AvaloniaUI/Avalonia/commit/7b192505d7b5dcc0eb9cb7afe675c161b62ae10f#diff-d949e9adb33714546ba0ea5e06af710cd80f33f7a446085b746577a334fb8637R216
Flyouts themselves aren’t added to any tree, but the underlying popup is when opened (otherwise Styling wouldn’t work). It’s using the indirect method instead of adding it to the actual LogicalChildren collection: https://github.com/AvaloniaUI/Avalonia/blob/99b4530e455cf64f9c5a392dbeb5a95974e0c792/src/Avalonia.Controls/Flyouts/FlyoutBase.cs#L225
Printing the logical parent hierarchy shows everything is connected all the way up to the main window:
However inspecting that button (and everything from the Popup down) shows it’s
TemplatedParentproperty is null, and I believe that’s set by the Xaml compiler when it parses the template. So I *think* this is a Xaml compiler thing. I don’t really understand how that works, so someone who does may have better insight but my guess is either A) it sees the Flyout as not a styleable object and seems to lose its scope when parsing the Flyout part of the template, or B) because those items aren’t connected to the logical/visual tree at parsing, it keeps the TemplatedParent property null by ignoring them. (or even possibly a little of both).