WPF ListBox of Buttons: how to change selected item on click with XAML
16,068
Solution 1
Typically you style your DataTemplate
to look and respond like a button if that is the effect you want e.g.
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="3" CornerRadius="10" Background="#FFD6D3D3" Margin="5">
<Border x:Name="myBorder" BorderBrush="#FFD6D3D3" BorderThickness="4" CornerRadius="10" Padding="2">
<Border.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1" >
<GradientStop Color="#FFA5A5A5" Offset="1"/>
<GradientStop Color="White"/>
</LinearGradientBrush>
</Border.Background>
<StackPanel>
<Image Source="{Binding Icon}" MaxHeight="32" MaxWidth="32"/>
<TextBlock x:Name="TxtContent" Text="{Binding Label}"/>
</StackPanel>
</Border>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}" Value="True">
<Setter TargetName="myBorder" Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,1" EndPoint="0.5,0">
<GradientStop Color="#FFA5A5A5" Offset="1"/>
<GradientStop Color="White" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter TargetName="TxtContent" Property="RenderTransform" >
<Setter.Value>
<TranslateTransform Y="2.0" />
</Setter.Value>
</Setter>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
You may also want to set the ItemContainerStyle
to override the default styling for the SelectedItem
:
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
Solution 2
The button defined in your DataTemplate
will be intercepting the click event before the ListBoxItem
can handle it. Remove the ItemContainerStyle
and the Button
from your DataTemplate
.
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Source="{Binding Icon}" MaxHeight="32" MaxWidth="32"/>
<TextBlock Text="{Binding Label}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
Comments
-
Nitin Chhajer almost 2 years
I have a templated
ListBox
:<ListBox Grid.Row="0" Grid.Column="1" Background="Transparent" BorderThickness="0" x:Name="mainMenu" ItemsSource="{Binding Source={x:Static local:MenuConfig.MainMenu}, Mode=OneTime}" IsSynchronizedWithCurrentItem="True"> <ListBox.ItemContainerStyle> <Style TargetType="ListBoxItem"> <EventSetter Event="PreviewMouseUp" Handler="SelectCurrentItem"/> </Style> </ListBox.ItemContainerStyle> <ListBox.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal"></StackPanel> </ItemsPanelTemplate> </ListBox.ItemsPanel> <ListBox.ItemTemplate> <DataTemplate> <Button> <StackPanel> <Image Source="{Binding Icon}" MaxHeight="32" MaxWidth="32"/> <TextBlock Text="{Binding Label}"/> </StackPanel> </Button> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
The selected item is updated manually with code behind:
private void SelectCurrentItem(object sender, MouseButtonEventArgs e) { ListBoxItem item = (ListBoxItem) sender; item.IsSelected = true; }
Is there a way to do this (update selected item on button click) with XAML only ?