none
ComboBox如何自定义SelectionBoxItemTemplate RRS feed

  • 问题

  • 选择一项后,ComboBox默认的做法是将DataTemplate中的内容都显示在那个框框中,如果我想自定义显示的内容的话,应该怎么做呢?

    我在ControlTemplate中发现一个SelectionBoxItemTemplate,但访问是私有的,没法设置。-_-!

    求解答。(╯▽╰)

    2011年8月18日 10:58

答案

  • 反射的方法我测试了一下,是可以改变模板的,但是遗漏了一点,ComboBox本身在我们SelectionChanged之后,他会根据你所选中的Item来生成SelectionBoxItemTemplate的。所以我们反射改变是无效的事实上。

    所以还是用第一种方法吧,修改ComboBox的模板,用自己的Temlate来哦替换掉

    <ContentPresenter Grid.Column="1" Content="{TemplateBinding ComboBox.SelectionBoxItem}" ContentStringFormat="{TemplateBinding ComboBox.SelectionBoxItemStringFormat}" ContentTemplate="{TemplateBinding ComboBox.SelectionBoxItemTemplate}" HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" IsHitTestVisible="False" Margin="{TemplateBinding Control.Padding}" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" />

    这个里面的 ContentTemplate="{TemplateBinding ComboBox.SelectionBoxItemTemplate}"  代码。 


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 Behindmoon 2011年8月23日 8:12
    2011年8月22日 12:22
    版主

全部回复

  • 修改ComboBox默认模板就可以,看我例子:

    <Window x:Class="WpfApplication2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525" xmlns:my="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
        <Window.Resources>
            <ControlTemplate x:Key="Template1" TargetType="ComboBox">
                <Grid Name="MainGrid" SnapsToDevicePixels="True">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0" />
                    </Grid.ColumnDefinitions>
                    <Popup AllowsTransparency="True" Grid.ColumnSpan="2" IsOpen="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" Name="PART_Popup" Placement="Bottom" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}">
                        <my:SystemDropShadowChrome Color="Transparent" MaxHeight="{TemplateBinding ComboBox.MaxDropDownHeight}" MinWidth="{Binding Path=ActualWidth, ElementName=MainGrid}" Name="Shdw">
                            <Border Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Name="DropDownBorder">
                                <ScrollViewer Name="DropDownScrollViewer">
                                    <Grid RenderOptions.ClearTypeHint="Enabled">
                                        <Canvas Height="0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="0">
                                            <Rectangle Fill="{Binding Path=Background, ElementName=DropDownBorder}" Height="{Binding Path=ActualHeight, ElementName=DropDownBorder}" Name="OpaqueRect" Width="{Binding Path=ActualWidth, ElementName=DropDownBorder}" />
                                        </Canvas>
                                        <ItemsPresenter KeyboardNavigation.DirectionalNavigation="Contained" Name="ItemsPresenter" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
                                    </Grid>
                                </ScrollViewer>
                            </Border>
                        </my:SystemDropShadowChrome>
                    </Popup>
                    <ToggleButton Background="{TemplateBinding Control.Background}" BorderBrush="{TemplateBinding Control.BorderBrush}" Grid.ColumnSpan="2" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}">
                        <ToggleButton.Style>
                            <Style TargetType="ToggleButton">
                                <Setter Property="FrameworkElement.OverridesDefaultStyle" Value="True" />
                                <Setter Property="Control.IsTabStop" Value="False" />
                                <Setter Property="UIElement.Focusable" Value="False" />
                                <Setter Property="ButtonBase.ClickMode" Value="Press" />
                                <Setter Property="Control.Template">
                                    <Setter.Value>
                                        <ControlTemplate TargetType="ToggleButton">
                                            <my:ButtonChrome Background="{TemplateBinding Control.Background}" BorderBrush="{TemplateBinding Control.BorderBrush}" Name="Chrome" RenderMouseOver="{TemplateBinding UIElement.IsMouseOver}" RenderPressed="{TemplateBinding ButtonBase.IsPressed}" SnapsToDevicePixels="True">
                                                <Grid HorizontalAlignment="Right" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}">
                                                    <Path Data="M0,0L3.5,4 7,0z" Fill="Black" HorizontalAlignment="Center" Margin="3,1,0,0" Name="Arrow" VerticalAlignment="Center" />
                                                </Grid>
                                            </my:ButtonChrome>
                                            <ControlTemplate.Triggers>
                                                <Trigger Property="ToggleButton.IsChecked" Value="True">
                                                    <Setter Property="my:ButtonChrome.RenderPressed" TargetName="Chrome" Value="True" />
                                                </Trigger>
                                                <Trigger Property="UIElement.IsEnabled" Value="False">
                                                    <Setter Property="Shape.Fill" TargetName="Arrow" Value="#FFAFAFAF" />
                                                </Trigger>
                                            </ControlTemplate.Triggers>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </ToggleButton.Style>
                    </ToggleButton>
                    <!-- 这里加内容 -->
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <Border BorderBrush="Blue" BorderThickness="2" Margin="2">
                            <TextBlock Text="自定义的ComboBox内容 : "/>
                        </Border>
                        <ContentPresenter Grid.Column="1" Content="{TemplateBinding ComboBox.SelectionBoxItem}" ContentStringFormat="{TemplateBinding ComboBox.SelectionBoxItemStringFormat}" ContentTemplate="{TemplateBinding ComboBox.SelectionBoxItemTemplate}" HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" IsHitTestVisible="False" Margin="{TemplateBinding Control.Padding}" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" />
                    </Grid>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="Popup.HasDropShadow" SourceName="PART_Popup" Value="True">
                        <Setter Property="FrameworkElement.Margin" TargetName="Shdw" Value="0,0,5,5" />
                        <Setter Property="my:SystemDropShadowChrome.Color" TargetName="Shdw" Value="#71000000" />
                    </Trigger>
                    <Trigger Property="ItemsControl.HasItems" Value="False">
                        <Setter Property="FrameworkElement.Height" TargetName="DropDownBorder" Value="95" />
                    </Trigger>
                    <Trigger Property="UIElement.IsEnabled" Value="False">
                        <Setter Property="Control.Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
                        <Setter Property="Control.Background" Value="#FFF4F4F4" />
                    </Trigger>
                    <Trigger Property="ItemsControl.IsGrouping" Value="True">
                        <Setter Property="ScrollViewer.CanContentScroll" Value="False" />
                    </Trigger>
                    <Trigger Property="ScrollViewer.CanContentScroll" SourceName="DropDownScrollViewer" Value="False">
                        <Setter Property="Canvas.Top" TargetName="OpaqueRect" Value="{Binding Path=VerticalOffset, ElementName=DropDownScrollViewer}" />
                        <Setter Property="Canvas.Left" TargetName="OpaqueRect" Value="{Binding Path=HorizontalOffset, ElementName=DropDownScrollViewer}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Window.Resources>
        <Grid>
            <ComboBox SelectedIndex="0" Template="{StaticResource Template1}" HorizontalAlignment="Center" VerticalAlignment="Center">
                <ComboBoxItem>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="Item 1"/>
                        <Ellipse Fill="Red" Width="100" Height="30"/>
                    </StackPanel>
                </ComboBoxItem>
                <ComboBoxItem>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="Item 2"/>
                        <Rectangle Fill="Green" Width="100" Height="30"/>
                    </StackPanel>
                </ComboBoxItem>
            </ComboBox>
        </Grid>
    </Window>
    

    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年8月18日 17:48
    版主
  • Hi, Bob :)

    我看了一下,这个只是在选择框前加上固定的内容。和我的需求不太符合,= =! 举个例子:

    我的Item是绑定的,DataTemplate中绑定了一张图片和一段文本,这样的话,默认的情况是当选择一项后,选择框中出现DataTemplate的所有内容,而我想要显示的仅仅是一张图片,不需要文字,即有选择地提取DataTemplate中的绑定内容,这个应该怎么做?O.O

    2011年8月19日 2:04
  • 在你确认选中之后通过Visual Tree Helper来修改ComboBox里面的内容。

    还有,ComboBox.SelectionBoxItemTemplate 虽然是私有的set方法,但是我们还是可以通过反射来修改的:

      typeof(ComboBox).GetProperty("SelectionBoxItemTemplate").SetValue(combobox, value, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance,null, null, null)
    

    Sincerely,

     

     


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年8月21日 15:42
    版主
  • 我将

     typeof(ComboBox).GetProperty("SelectionBoxItemTemplate").SetValue(cmbOnlineState, (DataTemplate)Resources["dt"], System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null, null, null);
    

    放在窗体的构造函数中,无效啊~

    <Window.Resources>
        <DataTemplate x:Key="dt">
          <Image Source="{Binding Bitmap}" Width="16" Height="16"></Image>
        </DataTemplate>
      </Window.Resources>
    
    <ComboBox x:Name="cmbOnlineState" Style="{StaticResource OnlineStateComboBox}" ItemContainerStyle="{StaticResource OnlineStateComboBoxItem}">
          <ComboBox.ItemTemplate>
            <DataTemplate>
              <Grid>
                <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="30" />
                  <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <Image Source="{Binding Bitmap}" Width="16" Height="16" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="0 3 0 3"></Image>
                <TextBlock Grid.Column="1" Text="{Binding Text}" VerticalAlignment="Center" Margin="0 0 10 0"></TextBlock>
              </Grid>
            </DataTemplate>
          </ComboBox.ItemTemplate>
        </ComboBox>
    



    2011年8月22日 11:39
  • 反射的方法我测试了一下,是可以改变模板的,但是遗漏了一点,ComboBox本身在我们SelectionChanged之后,他会根据你所选中的Item来生成SelectionBoxItemTemplate的。所以我们反射改变是无效的事实上。

    所以还是用第一种方法吧,修改ComboBox的模板,用自己的Temlate来哦替换掉

    <ContentPresenter Grid.Column="1" Content="{TemplateBinding ComboBox.SelectionBoxItem}" ContentStringFormat="{TemplateBinding ComboBox.SelectionBoxItemStringFormat}" ContentTemplate="{TemplateBinding ComboBox.SelectionBoxItemTemplate}" HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" IsHitTestVisible="False" Margin="{TemplateBinding Control.Padding}" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" />

    这个里面的 ContentTemplate="{TemplateBinding ComboBox.SelectionBoxItemTemplate}"  代码。 


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 Behindmoon 2011年8月23日 8:12
    2011年8月22日 12:22
    版主