WPF ListBox of Buttons: how to change selected item on click with XAML
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) sende开发者_如何转开发r;
item.IsSelected = true;
}
Is there a way to do this (update selected item on button click) with XAML only ?
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>
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>
A ListBox
tracks and selects the current item for you, you dont need to do it in code. remove this
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<EventSetter Event="PreviewMouseUp" Handler="SelectCurrentItem"/>
</Style>
</ListBox.ItemContainerStyle>
you are doing work thats done for you out of the box.
精彩评论