ListBox复选框拓展

时间:2023-03-09 04:35:27
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=""/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Padding" Value=""/>
<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="" Value="{StaticResource TransparentBrush}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Duration="" 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="" 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="" IsChecked="{TemplateBinding IsSelected}" Visibility="Collapsed"/>
<ContentControl x:Name="ContentContainer" Grid.Column="" 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>

ListBox复选框拓展

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

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

ListBox复选框拓展

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