How to highlight listbox's item on rightclick event?
-
27-09-2019 - |
Question
I don't know if I'm the first to ask this question(I searched the whole board) but I never found any answers. As said in the title I am trying to highlight/select an item in my Listbox whenever I right click it.
Here is the XAML code:
<ListBox Grid.Row="1" x:Name="ContactList" Margin="6" ItemsSource="{Binding ''}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Status_Image}" Margin="0,0,3,0" />
<StackPanel Orientation="Vertical">
<TextBlock Height="20" HorizontalAlignment="Left" Text="{Binding Name}" FontWeight="Bold" FontSize="13" Foreground="Black" />
<TextBlock Height="20" HorizontalAlignment="Left" Text="{Binding Message}" FontSize="11" Foreground="Gray" />
</StackPanel>
<Image Source="{Binding NotifImg}" Margin="8,0,0,0"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I know how to handle right click and show a Context menu on a button or a single element, but not on a bound Listbox. If you have any advices on how I should proceed please feel free to tell me because I'm currently stuck.
Thank you, Ephismen.
Solution
Alright I found a very simple and clean way of achieving what I wanted to do!
Here is the XAML code:
<ListBox Grid.Row="1" x:Name="ContactList"ItemsSource="{Binding ''}" MouseRightButtonDown="ContactList_MouseRightButtonDown" MouseRightButtonUp="ContactList_MouseRightButtonUp">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<TextBlock Height="20" HorizontalAlignment="Left" Text="{Binding Name}" FontWeight="Bold" FontSize="13" Foreground="Black" />
<TextBlock Height="20" HorizontalAlignment="Left" Text="{Binding Message}" FontSize="11" Foreground="Gray" />
<Image Source="{Binding NotifImg}" Margin="8,0,0,0"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And the code behind:
private void ContactList_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
e.Handled = true;
}
private void ContactList_MouseRightButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
VisualTreeHelper.FindElementsInHostCoordinates(e.GetPosition(null), (sender as ListBox)).OfType<ListBoxItem>().First().IsSelected = true;
}
Don't forget to include System.Linq for the 'OfType'.
Ephismen.
OTHER TIPS
Multiselection mode solution
The solution from Ephismen above does not work correctly for a ListBox in multiselection mode (e.g. it doesn't toggle item's selected state when Ctrl is down, it does not deselect other items when Ctrl is not down, ...).
I would suggest to create a custom ListBoxItem instead, with a custom right mouse click handler. There you can simulate a left mouse button click and thus get exactly the same behavior:
public class CustomListBoxItem : ListBoxItem
{
protected override void OnMouseRightButtonDown(MouseButtonEventArgs e)
{
OnMouseLeftButtonDown(e);
}
}
You may also need to create a simple converter for the ItemsSource
binding - to replace the standard ListBoxItem
, which would be created by default, by your CustomListBoxItem
:
public class ItemsToCustomListBoxItemsConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return null;
return
from object item in (IEnumerable) value
select new CustomListBoxItem
{
Content = item
};
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new InvalidOperationException();
}
}
And here's how the ItemsSource binding would look like:
<ListBox
...
ItemsSource="{Binding Converter={StaticResource ItemsToCustomListBoxItemsConverter}}"
...>