SetCurrentValue issue?
See original GitHub issueDescribe the bug While looking at #10652, it seems that change (which still needs to be done), doesn’t entirely fix my issue. Essentially the problem is this:
- NavigationView hosts a SplitView,
IsPaneOpen
is two-way bounds between them
If the SplitView is in an “overlay” state (CompactOverlay for example), clicking any where (that isn’t the pane) in the window should close the pane. With the NavigationView, that’s no longer working. The SplitView events are running correctly, but there’s 2 property changes fired for IsPaneOpen if you trigger the light dismiss, the first is false (expected), and the second reverts it back to true. Following the call stack, when the pane opens or closes, it triggers a pseudoclass/style trigger that modifies a couple properties of the SplitView (PaneBackground and BorderBrush), and this style trigger seems to be causing the value store to “re-evaluate frames” with an old value of IsPaneOpen
that’s still set to true - which overrides the recently changed using SetCurrentValue. From what I can tell, this style trigger right after SetCurrentValue is the key.
I’ve managed to pull out a minimal repro of the issue (just pop this into the Sandbox app). Run and click anywhere that isn’t the pane - the pane should collapse then, but it doesn’t. You can set a break point in SplitView OnPropertyChanged for IsPaneOpen and see the two events there too
public class TestControl : TemplatedControl
{
public static readonly StyledProperty<bool> IsPaneOpenProperty =
SplitView.IsPaneOpenProperty.AddOwner<TestControl>(
new StyledPropertyMetadata<bool>(defaultValue: true));
public bool IsPaneOpen
{
get => GetValue(IsPaneOpenProperty);
set => SetValue(IsPaneOpenProperty, value);
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == IsPaneOpenProperty)
{
PseudoClasses.Set(":panenotoverlaying", !change.GetNewValue<bool>());
}
}
}
<Window.Resources>
<ControlTheme TargetType="local:TestControl"
x:Key="{x:Type local:TestControl}">
<Setter Property="Template">
<ControlTemplate>
<Panel>
<SplitView IsPaneOpen="{TemplateBinding IsPaneOpen, Mode=TwoWay}"
BorderBrush="{DynamicResource NavigationViewItemSeparatorForeground}"
DisplayMode="CompactOverlay"
PaneBackground="#32000000"
Name="RootSplitView">
Test Content
</SplitView>
</Panel>
</ControlTemplate>
</Setter>
<Style Selector="^:panenotoverlaying">
<Style Selector="^ /template/ SplitView#RootSplitView">
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="PaneBackground" Value="#32FF0000" />
</Style>
</Style>
</ControlTheme>
</Window.Resources>
<local:TestControl />
EDIT:
Here’s the callstack and what the value store looks like when ReevaluateFrames
is called AFTER IsPaneOpen
is initally set to false
In ReevaluateFrames:
The SplitView
has 6 frames in the value store,
[0],[1],[3],[4] all have null
value for _entries
or are irrelevant, and [5] is related to the style trigger
[2] are all entries related to the TemplateBinding
where it shows IsPaneOpen
having a value of true
, which at this point *should* be false
Issue Analytics
- State:
- Created 6 months ago
- Comments:7 (7 by maintainers)
Top GitHub Comments
I think I may know what the problem is here. Investigating.
Hopefully fixed by #10695