WPF绑定的ListBox获取ListBoxItem及GoToState应用

现公司项目中需要制作一个扇形菜单,菜单项是用ListBox重写Style实现的,其数据是绑定的。菜单的每一项都有Normal,MouseOver和Selected三种状态,这三种状态当然可以通过鼠标移动和点击控制,但现在要通过代码来改变控件外观实现三种状态切换,该如何处理呢?

WPF绑定的ListBox获取ListBoxItem及GoToState应用
 
1.WPF绑定的ListBox获取ListBoxItem
 
WPF中如果ListBox的ItemSource为绑定的,则ListBox.Items为绑定的数据源,而非ListBoxItem。如果直接通过如下代码会发现无法获取ListBoxItem: 
var listBoxItem = ListBox1.Items[0] as List1BoxItem;

这时提示listBoxItem为null,那该如何获取到ListBoxItem呢?这时就用到了ItemContainerGenerator.ContainerFromIndex(int index)方法,该方法返回对应于 System.Windows.Controls.ItemCollection 中指定索引项的元素:

var listBoxItem = ListBox1.ItemContainerGenerator.ContainerFromIndex(0) as FrameworkElement;

这次就获取到了ListBox1中第一个listBoxItem。

2.WPF中的手动控制控件外观变化

如何在不移动鼠标的情况下触发ListBoxItem的MouseOver状态发生呢?这时就利用到了VisualStateManager.GoToState(FrameworkElement control, string stateName, bool useTransitions)方法。该方法可以使控件在两个状态间随意转换:

首先,为项目中的ListBoxItem自定义一个Style,其包含Normal和MouseOver两种状态:

<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>

为ListBox1应用样式,绑定数据源,拖出两个button分别用于设置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>

后台找到ListBoxItem并改变其外观:

 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);

        }

效果:

WPF绑定的ListBox获取ListBoxItem及GoToState应用WPF绑定的ListBox获取ListBoxItem及GoToState应用

你可能感兴趣的:(listbox)