Silverlight 多选组合框






4.39/5 (12投票s)
关于如何为 Silverlight 创建多选组合框的教程。
引言
ComboBox
是一个广泛使用的控件。有时,我们希望超越它的默认功能,例如多选。在本文中,我将带领大家一起创建一个 Silverlight 的多选 ComboBox
。同样的方法也适用于 WPF。我将使用 Expression Blend 进行设计。使用 Blend 创建资源骨架非常高效;您可以使用 Blend 或 Visual Studio 编辑代码。
在此更新版本中,我回答了最常被问到的问题:如何显示选中的项?
分步指南
目标是创建一个多选 ComboBox
,如下图所示。下拉列表中的项应显示 CheckBox
。右侧的 ListBox
演示了相同的 XAML 代码也可用于多选 ListBox
。一石二鸟!

假设您已经放置了一个 ComboBox
,并希望使其支持多选。首先,右键单击 ComboBox
弹出上下文菜单。在菜单中,选择“编辑模板”->“编辑副本”。这将打开“创建样式资源”对话框。您可以在对话框中重命名默认的名称(键)。然后单击“确定”关闭对话框。

现在,您将在 .xaml 文件中获得 ComboBox
的默认模板。您可以在以下窗口中浏览详细信息,并了解 ComboBox
的工作原理:当您单击 ComboBox
时,它会弹出一个 Popup
控件。默认情况下,Popup
控件使用 ItemsPresenter
来显示 ComboBox
的 SourceItems
。我们需要将其替换为支持多选的 ListBox
。
技巧
- Windows 的主题设置会影响 Blend 生成的模板。我建议您 避免使用基础主题。
- Blend 生成的模板可能会因 Silverlight 版本不同而略有差异。如果您无法将 Silverlight 3 生成的
ComboBox
模板与 Silverlight 4 一起使用,请使用 Silverlight 4 重新生成它。
我们还需要将 ListBoxItem
替换为 CheckBox
,以便用户可以轻松识别选中状态。在 XAML 窗口中进行此操作会更有效。让我们创建如下的 CheckBoxListBoxItemStyle
样式:
<Style x:Key="CheckBoxListBoxItemStyle" TargetType="ListBoxItem">
<Setter Property="Foreground" Value="#FF000000" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid x:Name="RootElement">
<CheckBox ClickMode="Press" Content="{Binding Path=Name}"
IsChecked="{Binding Path=IsSelected, Mode=TwoWay}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
确保设置 ClickMode="Press";
和 Mode=TwoWay
。
我这里使用的数据非常简单:一个 Name
属性和一个 IsSelected
属性。

如下所示,在 ListBox
中将 ItemContainerStyle
设置为 CheckBoxListBoxItemStyle
:
<ListBox x:Name="lstBox" SelectionMode="Multiple"
ItemsSource="{TemplateBinding ItemsSource}"
ItemContainerStyle="{StaticResource CheckBoxListBoxItemStyle}"
HorizontalAlignment="Stretch" />
现在您可以构建并运行项目。在演示页面中,我包含了一个额外的 ListBox
,它绑定到相同的数据。ListBox
重用了相同的样式 CheckBoxListBoxItemStyle
。使用 ListBox
,您可以验证 ComboBox
和 ListBox
上的选择是否已更新。
现在是时候创建一个资源字典文件,并将资源(模板和样式)移到资源字典中了。
在折叠的 ComboBox
中显示选中的项似乎有些模糊,因为它被设计用来显示单个项。在这里,我们需要用户界面设计的创造力。例如,我们可以减小 ComboBox
的宽度,并使用单独的 ItemsControl
来显示选中的项。ItemsControl
绑定到与 ComboBox
相同的数据,但只显示选中的项。我们可以实现一个带有 IValueConverter
的转换器类,将 IsSelected bool
属性转换为 Visibility
。这样,ItemsControl
将只显示选中的项。
<ItemsControl ItemsSource="{Binding Data}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"
Visibility="{Binding IsSelected,
Converter={StaticResource BoolToVisibilityConverter}}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
此外,我们可以使用 Tooltip
来显示选中的项。下图显示了一个嵌入了 ItemsControl
的 Tooltip
。

以下是有关如何在 Tooltip
中嵌入 ItemsControl
的代码片段:
<ComboBox ItemsSource="{Binding Data}" Width="26" VerticalAlignment="Center"
Style="{StaticResource MultiSelComboBoxStyle}" >
<ToolTipService.ToolTip>
<ToolTip>
<ItemsControl ItemsSource="{Binding Data}" Margin="4" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"
Visibility="{Binding IsSelected,
Converter={StaticResource BoolToVisibilityConverter}}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ToolTip>
</ToolTipService.ToolTip>
</ComboBox>
结论
ComboBox
包含一个 Popup
控件,用于托管项选择控件。您可以替换默认控件来定制行为,例如多选。技术上讲,您可以将 UserControl
(或几乎任何控件)嵌入 Popup
控件中。这为创建更复杂的 UI 打开了大门。有关详细信息,请参阅 如何弹出任何内容?