In the current company project, you need to create a sector menu. The menu items are implemented by rewriting the style using ListBox, and their data is bound. Each menu item has three states: Normal, Mouseover, and selected. Of course, you can control the three States by moving the mouse and clicking, But now you need to implement three State switches by changing the control appearance through code, what should we do?
1. Retrieve listboxitem from ListBox bound to WPFIn WPF, if the itemsource of ListBox is bound, ListBox. items is the bound data source, not listboxitem. If you use the following code, you will find that the listboxitem cannot be obtained:
var listBoxItem = ListBox1.Items[0] as List1BoxItem;
The following message is displayed: listboxitem is null. How can I obtain listboxitem? The itemcontainergenerator. containerfromindex (INT index) method is used to return the elements corresponding to the specified index in system. Windows. Controls. itemcollection:
var listBoxItem = ListBox1.ItemContainerGenerator.ContainerFromIndex(0) as FrameworkElement;
This time, the first listboxitem in listbox1 is obtained.
2. manually control the widget appearance changes in WPF
How does one trigger the Mouseover status of listboxitem without moving the mouse? Then the visualstatemanager. gotostate (frameworkelement control, string statename, bool usetransitions) method is used. This method allows the control to be freely converted between two states:
First, define a style for listboxitem in the project, which contains normal and Mouseover statuses:
<Style x:Key="ListBoxItemStyle1" TargetType="{x:Type ListBoxItem}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListBoxItem}"> <Grid> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"> <Storyboard> <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle"> <EasingColorKeyFrame KeyTime="0" Value="#FF5CFD30"/> </ColorAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="MouseOver"> <Storyboard> <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle"> <EasingColorKeyFrame KeyTime="0" Value="#FF29B5B8"/> </ColorAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Disabled"/> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Rectangle x:Name="rectangle" Fill="#FF5AFB2E" Stroke="Black"/> <TextBlock HorizontalAlignment="Center" TextWrapping="Wrap" Text="{TemplateBinding Content}" VerticalAlignment="Center"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
Apply the style to listbox1, bind the data source, and drag two buttons to set the status of listboxitem:
<Grid> <ListBox x:Name="ListBox1" HorizontalAlignment="Left" Height="100" Margin="57,45,0,0" VerticalAlignment="Top" Width="100" ItemsSource="{Binding MenuList}" ItemContainerStyle="{DynamicResource ListBoxItemStyle1}" d:LayoutOverrides="HorizontalAlignment, VerticalAlignment"/> <Button x:Name="btnMouseOver" Content="MouseOver" HorizontalAlignment="Left" Margin="75,0,0,65.163" VerticalAlignment="Bottom" Width="75" Click="btnMouseOver_Click"/> <Button x:Name="btnNormal" Content="Normal" Margin="213,0,221,65.163" VerticalAlignment="Bottom" Click="btnNormal_Click"/> </Grid>
In the background, locate the listboxitem and change its appearance:
private void btnMouseOver_Click(object sender, RoutedEventArgs e) { var item = ListBox1.ItemContainerGenerator.ContainerFromIndex(2) as FrameworkElement; VisualStateManager.GoToState(item, "MouseOver", false); } private void btnNormal_Click(object sender, RoutedEventArgs e) { var item = ListBox1.ItemContainerGenerator.ContainerFromIndex(2) as FrameworkElement; VisualStateManager.GoToState(item, "Normal", false); }
Effect: