-
dotnetgeek posted this
After implementing my hidable WPF menu, I realized there was a bug when the menu items are bound.
Here is the change to the XAML.
<Window x:Class="AutoHideMenuBar.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" Title="MainWindow" Height="201" Width="259" xmlns:local="clr-namespace:AutoHideMenuBar"> <Window.Resources> <x:Array x:Key="Array" Type="sys:String"> <sys:String>Item 1</sys:String> <sys:String>Item 2</sys:String> </x:Array> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition /> </Grid.RowDefinitions> <local:HidableMenu VerticalAlignment="Top"> <MenuItem Header="_File"> <MenuItem Header="_New"/> <MenuItem Header="_Open"/> <Separator /> <MenuItem Header="E_xit"/> </MenuItem> <MenuItem Header="_Dynamic" ItemsSource="{StaticResource Array}" /> </local:HidableMenu> <StackPanel Grid.Row="1"> <TextBlock Text="Type in the box" Margin="5"/> <TextBox Margin="5"/> <Button Content="OK" Margin="10"/> </StackPanel> </Grid> </Window>
Note that the Help menu was replaced with a Dynamic menu that is bound to an array that is defined in the Window’s resources.
This then has the following adverve affect when opening the Dynamic menu:

The issue is that the call to LogicalTreeHelper.GetParent for the menu “Item 1” returns null.
My first attempted fix was to convert the itemIsChild to use the Parent property on the FrameworkElement. Which did not change the behavior. After reading the MSDN documentation I realized that LogicalTreeHelper.GetParent is only a wrapper class that calls the Parent property (handles a few more cases, but for this case that description will do).
Now for the fix that fixes the issue.
private bool itemIsChild(DependencyObject dependancyObject) { if (ReferenceEquals(dependancyObject, null)) return false; if (ReferenceEquals(dependancyObject, this)) return true; return itemIsChild(LogicalTreeHelper.GetParent(dependancyObject) ?? VisualTreeHelper.GetParent(dependancyObject)); }
After much reading on the difference between the visual tree and the logical tree, I am still not sure I understand it. If anyone has a good description for this behavior I would love to here it.