C#: Listbox Contextmenu for Listboxitems (WPF) - c#

i want for my Listbox in WPF a contextmenu.
I did it with a contextmenu for the whole listbox, but you can richt-click to get the contextmenu even if you don't click on a item.
I found something at google, but this didn't work out.
I tried something like this:
<ListBox Margin="5" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="{Binding Name}" Click="MenuItemName_Click"/>
<MenuItem Header="{Binding Capital}" Click="MenuItemCapital_Click"/>
<MenuItem Header="{Binding Population}" Click="MenuItemPopulation_Click"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I tried it with a textblock like in the example, with other elements like in other tutorials, i tired it without and many other things- but nothing worked. No contextmenu for my listbox items :(
later i tried something like this:
<ListBox.ItemTemplate>
<DataTemplate>
<ListBoxItem>
<ListBoxItem.ContextMenu>
<ContextMenu>
<MenuItem/>
</ContextMenu>
</ListBoxItem.ContextMenu>
</ListBoxItem>
</DataTemplate>
</ListBox.ItemTemplate>
But it didn't work too.
Can someone give me a hint/working example :)?
thank you

I would set the ContextMenu in the ListBoxItem's style, rather than in the DataTemplate:
<ListBox Name="simpleListBox"
ItemsSource="{Binding SimpleList}"
DisplayMemberPath="Name">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
...
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>

Related

C# WPF ContextMenu: MenuItem does not react to click

I have a C# WPF-Application. In the XAML i have a Datagrid, to which I have added a ContextMenu, that looks like this:
<DataGrid.ContextMenu>
<ContextMenu ItemsSource="{Binding Categories}">
<ContextMenu.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding Name}" Background="{Binding Brush}" Click="MenuItem_Click" Tag="{Binding Id}" />
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</DataGrid.ContextMenu>
When using the application it looks like this: http://imgur.com/3UTj1Xd
The problem is, that when clicking the color part of the box (which I'm guessing is part of some internal grid) the MenuItem_Click event is fired. However, when I'm clicking on the grey part of the MenuItem the click event is not fired. Does anyone know why it behaves this way? And is there a way to fix this?
Additionally, it would be great to be able to color the whole menu item, not just the small box inside. Is there a way to do this?
You could try to decrease the Padding of the ContextMenu and the BorderThickess of the MenuItems:
<DataGrid.ContextMenu>
<ContextMenu ItemsSource="{Binding Categories}" Padding="0">
<ContextMenu.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding Name}" Background="{Binding Brush}" Click="MenuItem_Click" Tag="{Binding Id}"
BorderThickness="0"/>
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</DataGrid.ContextMenu>
Or
<DataGrid.ContextMenu>
<ContextMenu ItemsSource="{Binding Categories}" Padding="0">
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding Name}" />
<Setter Property="Tag" Value="{Binding Id}" />
<Setter Property="Background" Value="{Binding Brush}" />
<EventSetter Event="Click" Handler="MenuItem_Click" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</DataGrid.ContextMenu>

Context Menu Item for ListBox in WPF

I want to display ContextMenu on right click of ListBoxItems in WPF. I tried below code, but ContextMenu is displaying where ListBoxItems are not there also. What I want is to display ContextMenu only on the right click of only ListBoxItems.
<Grid>
<ListBox x:Name="listofConnectedItems" Grid.Column="0" Grid.Row="0" ItemsSource="{Binding MyItems}" MouseRightButtonDown="listofConnectedItems_MouseRightButtonDown" ContextMenuOpening="listofConnectedItems_ContextMenuOpening" >
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Padding" Value="10">
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="_Start" Click="MenuItemStart_Click" />
<MenuItem Header="Sto_p" Click="MenuItemStop_Click" />
<MenuItem Header="_Clear" Click="MenuItemClear_Click" />
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
</Grid>
`
Here I attached the screenshot.
Can anybody Please get me through this. Thanks in advance
It should be in IntemContainerStyle:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Header="Open" />
<MenuItem Header="Edit" Command="Binding
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
I think the problem is that You didn't specified height and width of list box so it automaticaly scales to the window size. So technically Your code is working correctly but listbox is everywhere.
try with something like
<ListBox x:Name="listofConnectedItems" Grid.Column="0" Grid.Row="0" BorderThickness="5" Width="200" Height="200"...
and then rightclick outside the listbox

How to add ItemsSource to Combobox nested in ListBox Template from codebehind?

I have some problem with ComboBox nested in ListBox. I want to add the same ItemsSource(gained from database, adding from codebehind) to each of comboboxes created in ListBox, but don't know how. Any ideas how to do this?
</Window.Resources>
<Style x:Key="lbxKey" TargetType="ListBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate DataType="{x:Type Type1}">
<StackPanel Orientation="Horizontal" Width="Auto" HorizontalAlignment="Stretch">
<TextBlock TextTrimming="CharacterEllipsis" Width="200" Text="{Binding NAMETYPE1}" HorizontalAlignment="Left"></TextBlock>
<ComboBox HorizontalAlignment="Stretch" Tag="{Binding IDTYPE1}">
<ComboBox.ItemsSource>
<!-- no idea what should be here or even if this is needed -->
</ComboBox.ItemsSource>
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type Type2}">
<StackPanel Orientation="Horizontal" Width="100">
<TextBlock Text="{Binding NAMETYPE2}" TextTrimming="CharacterEllipsis"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
In codebehind:
lbxListbox.ItemsSource = observableCollectionFromDatabase;
//here should be sth to set ItemsSource for comboboxes in ListBox
There should be a collection type property in your item class (anything that implements IEnumerable will do). Then you would bind the ComboBox's ItemSource like this:
<ComboBox Tag="{Binding IDTYPE1}" ItemsSource="{Binding ITEMS}" ...>

Bind CheckBox to SelectedItem in ListBox

I have created a ListBox in WPF, which does the following:
It binds to a DataSource in my ViewModel. The ListBox contains Items and next to each item is a CheckBox. If the user clicks on a CheckBox, the Item is being selected and the Command will be executed. It works fine and the code for WPF looks like this:
<ListBox ItemsSource="{Binding OCAntwort}" SelectedItem="{Binding SelectedAntwort}" >
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!--ElementName=Window is the Name of the XAML (in root definition)-->
<CheckBox DataContext="{Binding DataContext, ElementName=Window}" Command="{Binding CheckAnswer}" CommandParameter="{Binding ElementName=cbox, Path=IsChecked}" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=IsSelected}" x:Name="cbox" HorizontalAlignment="Right"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Resources>
</ListBox>
Now I'm trying the same on Windows Store App, but there's no AncestorType... If I'm doing it like this:
<Style TargetType="ListBoxItem" x:Name="lbitem">
<CheckBox DataContext="{Binding DataContext, ElementName=Window}" Command="{Binding CheckAnswer}" CommandParameter="{Binding ElementName=cbox, Path=IsChecked}" IsChecked="{Binding ElementName=lbitem, Path=IsSelected}" x:Name="cbox" HorizontalAlignment="Left"/>
The Checkbox disappears and it'll just display the ItemsSource of OCAntwort. Clicking on an item won't execute the Command of the CheckBox (since there is no CheckBox).
Doing it like this:
IsChecked="{Binding ElementName=lbitem, Path=IsSelected,RelativeSource={RelativeSource Mode=Self}}"
would display the CheckBox and execute the Command, but it's not being binded to the SelectedItem.
How can I bind the CheckBox (which is being displayed next to the ListBoxItem for each ListBoxItem) to the SelectedItem of a ListBox? Working code is above... I want that the code should work in my Windows Store App (and later in my Windows Phone App).
Example:
You can download a sample here: http://weblogs.asp.net/marianor/archive/2008/02/04/multiselect-listview-with-checkboxes-in-wpf.aspx
This shows what I want to achieve in Windows Store App.
Edit: Doing it like this displays the ListBox with a content and a CheckBox, but I still need to bind the CheckBox by the SelectedItem. Means when the user clicks on a CheckBox, the ListBoxItem has to be selected or if the user clicks on a ListBoxItem, the CheckBox has to be selected.
<ListBox ItemsSource="{Binding OCAntwort}" SelectedItem="{Binding SelectedAntwort}" Grid.Row="2" Grid.Column="1" x:Name="listBox" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Text}" Width="150" VerticalAlignment="Center"/>
<CheckBox IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsSelected, Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Not sure if you've found the solution yet but I have used the following code to establish two way binding between the IsChecked property of a CheckBox and the IsSelected property of a parent ListBoxItem or ListViewItem.
<CheckBox IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}"/>
You should use TemplatedParent as you are writing inside the ListBoxItem.
IsChecked="{Binding ElementName=lbitem,
Path=IsSelected,
RelativeSource={RelativeSource Mode=TemplatedParent}}"
I think this may resolve your problem.

ToggleButton Checked Event Handling

I have ToggleButtons that are dynamically created based on my datasource. I would like to have only one togglebutton checked at a time when a user clicks one. How can I accomplish this?
<UserControl.Resources>
<ItemsPanelTemplate x:Key="HorizontalMiniDrawerList">
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
<DataTemplate x:Key="MiniDrawerRowTemplate">
<ToggleButton x:Name="_MiniDrawerButton" Width="60" Height="85" Style="{DynamicResource MiniDrawerButtonWhite}" Checked="_MiniDrawerButton_Checked" >
</ToggleButton>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Width}" Value="3">
<Setter TargetName="_MiniDrawerButton" Property="Width" Value="185"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<DataTemplate x:Key="MiniDrawerListItemTemplate">
<ListBox SelectionMode="Multiple" Background="#00000000" BorderThickness="0" Width="500"
ItemsPanel="{StaticResource HorizontalMiniDrawerList}"
ItemTemplate="{StaticResource MiniDrawerRowTemplate}"
ItemsSource="{Binding Row}" >
</ListBox>
</DataTemplate>
</UserControl.Resources>
<Grid Background="{DynamicResource ListBackgroundColor}" >
<ListBox x:Name="_MiniDrawerRows" BorderThickness="0" Background="Transparent" Margin="107,84,225,217" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding Path=MiniDrawerRows, diagnostics:PresentationTraceSources.TraceLevel=High}"
ItemTemplate="{StaticResource MiniDrawerListItemTemplate}" >
</ListBox>
</Grid>
Update: Instead of using a togglebutton I used a radiobutton and changed the style of the radio button to look like a togglebutton.
<Style x:Key="MiniDrawerButtonWhiteRadioToToggleButton" BasedOn="{StaticResource {x:Type ToggleButton}}" TargetType="{x:Type RadioButton}">
I assume you mean "only one" instead of "only when". In that case you can use RadioButton (which is derived from ToggleButton) instead and set a GroupName on _MiniDrawerButton in your ItemTemplate. It looks like you are probably already using a custom ControlTemplate so you can use the same one for RadioButton by just changing the Style and ControlTemplate TargetTypes.

Categories