I'm implementing a Vertical Left Drop Down Menu with an User Control, this has inside an Expander. The UserControl has a DependencyProperty which expect a ListView (The Items of the Menu), also has a dependency property "IsSelected" which is bind with Expander property "IsExpanded". I like implement a function when the user click in the UserControlMenu, open this (if is Closed) and close the others. I attached my classes and UserControl, but, now I'm only get when you click on the UserControlMenu, this open and in that instant close.
The UserControl XAML
<UserControl x:Class="DropDownMenuExpander.UserControlMenuItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d" >
<Grid>
<md:PackIcon Kind="{Binding Path=Icon}" Width="15" Height="15" Margin="10 16"/>
<Expander x:Name="ExpanderMenu" Header="{Binding Path=Header}" IsExpanded="{Binding Path=IsSelected}" Width="210" HorizontalAlignment="Right" Background="{x:Null}">
<ContentControl Content="{Binding ListView}"/>
</Expander>
</Grid>
</UserControl>
The UserControl .cs
public partial class UserControlMenuItem : UserControl
{
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register("Header", typeof(string), typeof(UserControlMenuItem));
public string Header
{
get
{
return (string)GetValue(HeaderProperty);
}
set
{
SetValue(HeaderProperty, value);
}
}
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(UserControlMenuItem));
public bool IsSelected
{
get
{
return (bool)GetValue(IsSelectedProperty);
}
set
{
SetValue(IsSelectedProperty, value);
}
}
public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(PackIconKind), typeof(UserControlMenuItem));
public PackIconKind Icon
{
get
{
return (PackIconKind)GetValue(IconProperty);
}
set
{
SetValue(IconProperty, value);
}
}
public static readonly DependencyProperty ListViewProperty = DependencyProperty.Register("ListView", typeof(ListView), typeof(UserControlMenuItem), new UIPropertyMetadata(null));
public ListView ListView
{
get
{
return (ListView)GetValue(ListViewProperty);
}
set
{
SetValue(ListViewProperty, value);
}
}
public UserControlMenuItem()
{
InitializeComponent();
DataContext = this;
}
}
Calling the UserControl in the MainWindow
<StackPanel x:Name="st_menu" Margin="10" Orientation="Vertical" ScrollViewer.CanContentScroll="True">
<local:UserControlMenuItem x:Name="MenuItemHome" Header="Home" Icon="Home" PreviewMouseDown="MenuItemHome_PreviewMouseDown">
<local:UserControlMenuItem.ListView>
<ListView SelectionMode="Single" Margin="0 16 0 16">
<ListViewItem>
<TextBlock Text="Item1"/>
</ListViewItem>
<ListViewItem>
<TextBlock Text="Item2"/>
</ListViewItem>
<ListViewItem>
<TextBlock Text="Item3"/>
</ListViewItem>
</ListView>
</local:UserControlMenuItem.ListView>
</local:UserControlMenuItem>
<local:UserControlMenuItem x:Name="MenuItem2" Header="User" Icon="User" PreviewMouseDown="MenuItemHome_PreviewMouseDown">
<local:UserControlMenuItem.ListView>
<ListView SelectionMode="Single" Margin="0 16 0 16">
<ListViewItem>
<TextBlock Text="User1"/>
</ListViewItem>
<ListViewItem>
<TextBlock Text="User2"/>
</ListViewItem>
<ListViewItem>
<TextBlock Text="User3"/>
</ListViewItem>
</ListView>
</local:UserControlMenuItem.ListView>
</local:UserControlMenuItem>
<local:UserControlMenuItem x:Name="MenuMes2" Header="Messages" Icon="Chat" PreviewMouseDown="MenuItemHome_PreviewMouseDown">
<local:UserControlMenuItem.ListView>
<ListView SelectionMode="Single" Margin="0 16 0 16">
<ListViewItem>
<TextBlock Text="Message1"/>
</ListViewItem>
<ListViewItem>
<TextBlock Text="Message2"/>
</ListViewItem>
<ListViewItem>
<TextBlock Text="Message3"/>
</ListViewItem>
</ListView>
</local:UserControlMenuItem.ListView>
</local:UserControlMenuItem>
</StackPanel>
MainWindow.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MenuItemHome.IsSelected = true;
}
private void MenuItemHome_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
foreach (var item in st_menu.Children)
{
if (item is UserControlMenuItem menuItem)
{
if (menuItem.Equals(sender as UserControlMenuItem))
{
menuItem.IsSelected = true;
}
else
{
menuItem.IsSelected = false;
}
}
}
}
}
You should set eventArgs.Handled = true;
, it will stop the event bubbling, like:
private void MenuItemHome_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
foreach (var item in st_menu.Children)
{
if (item is UserControlMenuItem menuItem && sender is UserControlMenuItem senderItem)
{
menuItem.IsSelected = menuItem.Equals(senderItem) && !senderItem.IsSelected;
e.Handled = true; //Tells to the visual tree that event was already handled
}
}
}