我一直在使用我的解决方案中的两个不同的组合框(部门和名称)这些组合框当前绑定到从外部服务引用返回的列表集合。我有一个问题是,我需要将其他元素插入到组合框中,而不是API提供的内容。
例如,除了显示所有部门名称之外,我还需要在组合框中可见的第一个元素是“选择部门......” 在进行一些研究(在这里和在线)时,看起来我可以使用复合集合来做到这一点。
http://zamjad.wordpress.com/2010/05/18/using-composite-collection-in-c/
我的问题是,我只有一个项目需要作为组合框中的第一项呈现,这是最好的方法吗?或者我需要看一些其他方法吗?
提前致谢,
答案 0 :(得分:2)
您可以通过更改ComboBox ControlTemplate直接在XAML中执行此操作,而不是仅仅为了在UI中显示临时值而弄乱您的数据。您可以在模板中设置触发器,以便在未选择任何内容时交换值。
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="SelectedIndex" Value="-1"/>
<Condition Property="IsDropDownOpen" Value="false"/>
<Condition Property="HasItems" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Content" TargetName="Presenter" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Tag}"/>
</MultiTrigger>
此版本为您提供了进一步的优势,因为它不允许在进行选择后选择空值。可以通过将标记设置为默认消息来使用它。
<ComboBox Tag="Select department..." Template="{StaticResource ComboBoxSelectTemplate}" ItemsSource="{Binding Departments}"/>
这是基于默认Aero模板的完整版本,需要添加dll引用和xmlns:Microsoft_Windows_Themes =“clr-namespace:Microsoft.Windows.Themes; assembly = PresentationFramework.Aero”(可以替换ButtonChrome和SystemDropShadowChrome)使用Border和DropShadow效果来避免添加引用):
<Geometry x:Key="DownArrowGeometry">M 0 0 L 3.5 4 L 7 0 Z</Geometry>
<Style x:Key="ComboBoxReadonlyToggleButton" TargetType="{x:Type ToggleButton}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="ClickMode" Value="Press"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}">
<Grid HorizontalAlignment="Right" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}">
<Path x:Name="Arrow" Fill="Black" HorizontalAlignment="Center" Margin="3,1,0,0" VerticalAlignment="Center" Data="{StaticResource DownArrowGeometry}"/>
</Grid>
</Microsoft_Windows_Themes:ButtonChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Fill" TargetName="Arrow" Value="#AFAFAF"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="ComboBoxSelectTemplate" TargetType="{x:Type ComboBox}">
<Grid x:Name="MainGrid" SnapsToDevicePixels="true">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
</Grid.ColumnDefinitions>
<Popup x:Name="PART_Popup" Margin="1" AllowsTransparency="true" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Bottom" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Grid.ColumnSpan="2">
<Microsoft_Windows_Themes:SystemDropShadowChrome x:Name="Shdw" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=MainGrid}" Color="Transparent">
<Border x:Name="DropDownBorder" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1">
<ScrollViewer CanContentScroll="true">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.DirectionalNavigation="Contained"/>
</ScrollViewer>
</Border>
</Microsoft_Windows_Themes:SystemDropShadowChrome>
</Popup>
<ToggleButton Style="{StaticResource ComboBoxReadonlyToggleButton}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/>
<ContentPresenter x:Name="Presenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" IsHitTestVisible="false" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"/>
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="SelectedIndex" Value="-1"/>
<Condition Property="IsDropDownOpen" Value="false"/>
<Condition Property="HasItems" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Content" TargetName="Presenter" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Tag}"/>
</MultiTrigger>
<Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true">
<Setter Property="Margin" TargetName="Shdw" Value="0,0,5,5"/>
<Setter Property="Color" TargetName="Shdw" Value="#71000000"/>
</Trigger>
<Trigger Property="HasItems" Value="false">
<Setter Property="Height" TargetName="DropDownBorder" Value="95"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
<Setter Property="Background" Value="#FFF4F4F4"/>
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
答案 1 :(得分:1)
听起来好像你想要的是一些元素在没有被选中时可见,并且看起来是ComboBox的一部分,但在做出选择时是不可见的。
最简单的说,您可以设计一个具有ComboBox的UserControl(如果您在代码中添加项目而不是某些静态XAML标记)以及包含提示的TextBlock。像这样:
<Grid>
<ComboBox x:Name="ComboBoxControl"
SelectionChanged="ComboBoxControl_SelectionChanged"
HorizontalAlignment="Left" VerticalAlignment="Top"
MinWidth="{Binding ElementName=UnselectedText, Path=ActualWidth}">
<ComboBoxItem>One</ComboBoxItem>
<ComboBoxItem>Two</ComboBoxItem>
<ComboBoxItem>Three</ComboBoxItem>
</ComboBox>
<TextBlock IsHitTestVisible="False"
x:Name="UnselectedText"
HorizontalAlignment="Left"
Text="Select an option..."
VerticalAlignment="Top" Margin="4"
Padding="0,0,30,0" />
</Grid>
然后,在代码隐藏中,在事件处理程序中插入一些逻辑:
Private Sub ComboBoxControl_SelectionChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs)
If ComboBoxControl.SelectedIndex = -1 Then
UnselectedText.Visibility = Windows.Visibility.Visible
Else
UnselectedText.Visibility = Windows.Visibility.Hidden
End If
End Sub
在TextBlock上设置IsHitTestVisible="False"
DependencyProperty允许鼠标事件通过,以便您可以单击ComboBox,并在代码隐藏中将可见性设置为Hidden
,保持默认ComboBox外观的布局在隐藏提示文本时跳转。
当然,所有这一切都可以通过创建一个继承自ComboBox的MyComboBox自定义控件来实现,并添加了“UnselectedPromptProperty”作为依赖属性。然后显示或隐藏“UnselectedPromptProperty”的逻辑将来自DP上的验证回调。这是更高级的,但它允许您将非默认样式模板传播到您的控件中,允许其他人重新调整它。
答案 2 :(得分:0)
我使用复合类在ComboBox中包含嵌入式辅助(“选择部门......”),我认为它运行良好。
用户选择部门后,我建议您删除嵌入式协助。