ListBox复选框拓展

Toolkit的LongListMutiSelector的复选框功能,想必许多人都需要吧!然而系统本身控件ListBox虽然也有多选功能,可是外观上却缺乏复选框,选择效果只是颜色变化。于是在上一个项目中只好选择LongListMutiSeletor作为列表的控件,项目结束后就有个想法对ListBox进行拓展,使ListBox列表可以拥有复选框。

之前为了修改LongListMutiSelector在白色背景下滚动条无法显示的问题,曾经仔细看了一下LongListMutiSelector相关的一些模版,发现LongListMutiSelector的复选框其实来自LongListMutiSelectorItem模版中的Checkbox。于是心中就有个想法,对ListBox的模版进行修改添加上Checkbox,然后再绑定上ListBox本身IsSelected属性,这样就可以实现复选框了。

说做就做,首先对模版进行拓展,添加Checkbox。

<Style TargetType="control:ListBoxItemEx">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="BorderBrush" Value="Transparent"/>
        <Setter Property="Padding" Value="0"/>
        <Setter Property="HorizontalContentAlignment" Value="Left"/>
        <Setter Property="VerticalContentAlignment" Value="Top"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="control:ListBoxItemEx">
                    <Border x:Name="LayoutRoot" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="MouseOver"/>
                                <VisualState x:Name="Disabled">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="LayoutRoot">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TransparentBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <DoubleAnimation Duration="0" To=".5" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ContentContainer"/>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="SelectionStates">
                                <VisualState x:Name="Unselected"/>
                                <VisualState x:Name="Selected">
                                    <Storyboard>
                                        <!--<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneAccentBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>-->
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="FocusStates"/>
                        </VisualStateManager.VisualStateGroups>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <CheckBox x:Name="checkBox" Grid.Column="0" IsChecked="{TemplateBinding IsSelected}" Visibility="Collapsed"/>
                            <ContentControl x:Name="ContentContainer" Grid.Column="1" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Grid>                       
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

 

 其次,再对ListBox进行继承拓展。增加SelectionEable属性,当属性更改显示或隐藏复选框。

 public ItemSelectionMode SelectionEable
        {
            get { return (ItemSelectionMode)GetValue(SelectionEableProperty); }
            set { SetValue(SelectionEableProperty, value); }
        }

        public static readonly DependencyProperty SelectionEableProperty = DependencyProperty.Register(
            "SelectionEable",
            typeof(ItemSelectionMode),
            typeof(ListBoxItemEx),
            new PropertyMetadata(ItemSelectionMode.Normal, OnSelectionEableChanged));

        private static void OnSelectionEableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ListBoxItemEx item = d as ListBoxItemEx;
            if (item.checkBox != null)
            {
                ItemSelectionMode mode = (ItemSelectionMode)e.NewValue;
                switch (mode)
                {
                    case ItemSelectionMode.Normal:
                        item.checkBox.Visibility = Visibility.Collapsed;
                        break;
                    case ItemSelectionMode.Selection:
                        item.checkBox.Visibility = Visibility.Visible;
                        break;
                }
            }
        }

Ok在页面前台写下以下代码,就会发现设计视图中的ListBoxItem有了复选框。

<MyControls:ListBoxItemEx SelectionEable="Selection">
            测试选项
        </MyControls:ListBoxItemEx>

拓展完ListBoxItem后事情还没完,这只是ListBoxItem有了复选框,ListBox并没有,还要对ListBox进行拓展才行。

同样拓展一个SlectionEable属性,并且将该属性和它的Item的SelectonEable属性关联起来。其次还得重载ListBox的GetContainerForItemOverride方法,返回一个重载后的ListBoxItemEx对象作为列表生产每一项内容的承载容器。这样就完成了对ListBox复选框的拓展。

ps:实际测试中发现复选框的IsChecked属性和ListBoxItem的IsSelected属性并没有同步,后面仔细查看文档后发现TemplateBinding并不能进行双向绑定,即前台Checkbox的勾选变化不会同步到IsSelected属性,而只有Binding和StaticResource可以进行双向绑定,于是将TemplateBinding改为Binding,Mode为TwoWay,这样就可以双向绑定了。

posted @ 2013-09-13 09:16  清风梧桐  阅读(1596)  评论(3编辑  收藏  举报