wpf 使用自定义项目模板在 ComboBox 中显示所选项目

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21776117/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 10:50:53  来源:igfitidea点击:

Show selected item in ComboBox with custom item template

c#wpfxamlbindingcombobox

提问by JohanDNB

I used the code from this page to style my combobox: How to style ComboBox Background on Mouse Hover?

我使用此页面中的代码来设置我的组合框的样式:如何在鼠标悬停时设置组合框背景样式?

I've changed my default item template, but now they won't appear in the selected value area. In the image below you can see the problem and what I want to achieve.

我已经更改了我的默认项目模板,但现在它们不会出现在选定的值区域中。在下图中,您可以看到问题以及我想要实现的目标。

Screenshot showing desired effect

显示所需效果的屏幕截图

This is my XAML in App.xaml:

这是我在 App.xaml 中的 XAML:

<LinearGradientBrush x:Key="ButtonBackgroundBrush" StartPoint="0,0" EndPoint="0,1">
    <GradientStop Offset="0" Color="#FFF3F3F3"/>
    <GradientStop Offset="0.3" Color="#FFCCCCCC"/>
</LinearGradientBrush>

<LinearGradientBrush x:Key="ButtonBackgroundBrush" StartPoint="0,0" EndPoint="0,1">
    <GradientStop Offset="0" Color="#FFF3F3F3"/>
    <GradientStop Offset="0.3" Color="#FFCCCCCC"/>
</LinearGradientBrush>

<LinearGradientBrush x:Key="ButtonBackgroundHoverBrush" StartPoint="0,0" EndPoint="0,1">
    <GradientStop Offset="0" Color="#FFE4E4E4"/>
    <GradientStop Offset="0.3" Color="#FFBBBBBB"/>
</LinearGradientBrush>

<LinearGradientBrush x:Key="ButtonBackgroundDisabledBrush" StartPoint="0,0" EndPoint="0,1">
    <GradientStop Offset="0" Color="#FF636363"/>
    <GradientStop Offset="0.3" Color="#FF4E4D4D"/>
</LinearGradientBrush>

<SolidColorBrush x:Key="GlyphBrush" Color="#FFF" />

<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />

<SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" />

<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="ToggleButton">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="20" />
        </Grid.ColumnDefinitions>

        <Border x:Name="Border" Grid.ColumnSpan="2" CornerRadius="2" Background="{StaticResource ButtonBackgroundBrush}" BorderBrush="#FF898989" BorderThickness="1" />
        <Border x:Name="Border2" Grid.Column="0" CornerRadius="2,0,0,2" Margin="1" Background="White" BorderBrush="#FF898989" BorderThickness="0,0,1,0" />

        <Path x:Name="Arrow" Grid.Column="1" Fill="{StaticResource GlyphBrush}" HorizontalAlignment="Center" VerticalAlignment="Center" Data="M 0 0 L 4 4 L 8 0 Z"/>
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="ToggleButton.IsMouseOver" Value="True">
            <Setter TargetName="Border" Property="Background" Value="{StaticResource ButtonBackgroundHoverBrush}" />
            <Setter TargetName="Border" Property="BorderBrush" Value="#FF59B7FF" />
            <Setter TargetName="Border2" Property="BorderBrush" Value="#FF59B7FF" />
        </Trigger>
        <Trigger Property="ToggleButton.IsChecked" Value="True">
            <Setter TargetName="Border" Property="Background" Value="{StaticResource ButtonBackgroundHoverBrush}" />
            <Setter TargetName="Border" Property="BorderBrush" Value="#FF59B7FF" />
            <Setter TargetName="Border2" Property="BorderBrush" Value="#FF59B7FF" />
        </Trigger>
        <Trigger Property="IsEnabled" Value="False">
            <Setter TargetName="Border" Property="Background" Value="{StaticResource ButtonBackgroundDisabledBrush}" />
            <Setter TargetName="Arrow" Property="Fill" Value="{StaticResource DisabledForegroundBrush}" />
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

<ControlTemplate x:Key="ComboBoxTextBox" TargetType="TextBox">
    <Border x:Name="PART_ContentHost" Focusable="False" Background="{TemplateBinding Background}" />
</ControlTemplate>

<Style x:Key="{x:Type ComboBox}" TargetType="ComboBox">
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="OverridesDefaultStyle" Value="True"/>
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
    <Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
    <Setter Property="MinWidth" Value="120"/>
    <Setter Property="MinHeight" Value="20"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ComboBox">
                <Grid>
                    <ToggleButton Name="ToggleButton" Template="{StaticResource ComboBoxToggleButton}" Grid.Column="2" Focusable="False" IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" />
                    <ContentPresenter Name="ContentSite" IsHitTestVisible="False" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Margin="3,3,23,3" VerticalAlignment="Center" HorizontalAlignment="Left" />
                    <TextBox x:Name="PART_EditableTextBox" Style="{x:Null}" Template="{StaticResource ComboBoxTextBox}" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="3,3,23,3" Focusable="True" Background="Transparent" Visibility="Hidden" IsReadOnly="{TemplateBinding IsReadOnly}" />
                    <Popup Name="Popup" Placement="Bottom" IsOpen="{TemplateBinding IsDropDownOpen}" AllowsTransparency="True" Focusable="False" PopupAnimation="Slide">
                        <Grid Name="DropDown" SnapsToDevicePixels="True" MinWidth="{TemplateBinding ActualWidth}" MaxHeight="{TemplateBinding MaxDropDownHeight}">
                            <Border x:Name="DropDownBorder" Background="White" BorderThickness="1" BorderBrush="#FF898989" />
                            <ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
                                <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
                            </ScrollViewer>
                        </Grid>
                    </Popup>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="HasItems" Value="False">
                        <Setter TargetName="DropDownBorder" Property="MinHeight" Value="95"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
                    </Trigger>
                    <Trigger Property="IsGrouping" Value="True">
                        <Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
                    </Trigger>
                    <Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="True">
                        <Setter TargetName="DropDownBorder" Property="CornerRadius" Value="0,0,2,2"/>
                        <Setter TargetName="DropDownBorder" Property="Margin" Value="0,-1,0,0"/>
                    </Trigger>
                    <Trigger Property="IsEditable" Value="True">
                        <Setter Property="IsTabStop" Value="False"/>
                        <Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible"/>
                        <Setter TargetName="ContentSite" Property="Visibility" Value="Hidden"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Name="CustomComboboxItem" TargetType="ComboBoxItem">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ComboBoxItem">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="30"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <Grid Grid.Column="1">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="16" MinHeight="16" MaxHeight="16" />
                            <RowDefinition Height="16" MinHeight="16" MaxHeight="16" />
                        </Grid.RowDefinitions>
                        <TextBlock Text="{Binding NewItemName}" Grid.Row="0" FontWeight="Bold" />
                        <TextBlock Text="{Binding NewItemComment}" Grid.Row="1" FontStyle="Italic" Foreground="#FF555454" />
                    </Grid>
                </Grid>

                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="LightGray"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

MainWindow.xaml:

主窗口.xaml:

<ComboBox Height="40" HorizontalAlignment="Left" Margin="102,64,0,0" Name="comboBox1" VerticalAlignment="Top" Width="459" />

Code-behind:

代码隐藏:

public MainWindow()
{
    InitializeComponent();

    comboBox1.Items.Add(new CustomComboboxItem { NewItemName = "Item 1", NewItemComment = "hello :)" });
    comboBox1.Items.Add(new CustomComboboxItem { NewItemName = "Item 2", NewItemComment = "hello :)" });
    comboBox1.Items.Add(new CustomComboboxItem { NewItemName = "Item 3", NewItemComment = "hello :)" });
    comboBox1.Items.Add(new CustomComboboxItem { NewItemName = "Item 4", NewItemComment = "hello :)" });
    comboBox1.Items.Add(new CustomComboboxItem { NewItemName = "Item 5", NewItemComment = "hello :)" });
}

public class CustomComboboxItem
{
    public string NewItemName { get; set; }
    public string NewItemComment { get; set; }
}

Can someone tell me what I'm doing wrong?

有人可以告诉我我做错了什么吗?

回答by har07

You can define ItemTemplate for ComboBox instead of ControlTemplate for ComboBoxItem to achieve that. As you can see, ControlTemplate for ComboBoxItem doesn't affect selected item appearance when ItemTemplate does. Following is content of your CustomComboboxItemStyle merged within ComboBox Style :

您可以为 ComboBox 定义 ItemTemplate 而不是为 ComboBoxItem 定义 ControlTemplate 来实现这一点。如您所见,当 ItemTemplate 影响时,ComboBoxItem 的 ControlTemplate 不会影响所选项目的外观。以下是CustomComboboxItem合并到 ComboBox Style 中的 Style 内容:

<Style x:Key="{x:Type ComboBox}" TargetType="ComboBox">
        ........
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        <Setter Property="ItemTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Grid>
                        <Grid.Style>
                            <Style TargetType="Grid">
                                <Style.Triggers>
                                    <Trigger Property="IsMouseOver" Value="True">
                                        <Setter Property="Background" Value="LightGray"/>
                                    </Trigger>
                                </Style.Triggers>
                            </Style>
                        </Grid.Style>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="30"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Grid Grid.Column="1">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="16" MinHeight="16" MaxHeight="16" />
                                <RowDefinition Height="16" MinHeight="16" MaxHeight="16" />
                            </Grid.RowDefinitions>
                            <TextBlock Text="{Binding NewItemName}" Grid.Row="0" FontWeight="Bold" />
                            <TextBlock Text="{Binding NewItemComment}" Grid.Row="1" FontStyle="Italic" Foreground="#FF555454" />
                        </Grid>
                    </Grid>
                </DataTemplate>
            </Setter.Value>
        </Setter>
        ........
    </Style>

回答by Piotr Klimaszewski

You should override toString()method of CustomComboboxItemclass.

您应该覆盖类的toString()方法CustomComboboxItem

回答by Sankarann

<Style x:Name="CustomComboboxItem" TargetType="ComboBoxItem">

Replace the above code with

将上面的代码替换为

<Style x:Key="{x:Type ComboBoxItem}" TargetType="ComboBoxItem">

Remove the x:Name..

删除x:Name..

    public MainWindow()
    {
        InitializeComponent();
        var itemSource = new System.Collections.ObjectModel.ObservableCollection<CustomComboboxItem>();

        itemSource.Add(new CustomComboboxItem {NewItemName = "Item 1", NewItemComment = "hello :)"});
        itemSource.Add(new CustomComboboxItem {NewItemName = "Item 2", NewItemComment = "hello :)"});
        itemSource.Add(new CustomComboboxItem {NewItemName = "Item 3", NewItemComment = "hello :)"});
        itemSource.Add(new CustomComboboxItem {NewItemName = "Item 4", NewItemComment = "hello :)"});
        itemSource.Add(new CustomComboboxItem {NewItemName = "Item 5", NewItemComment = "hello :)"});

        comboBox1.ItemSource = itemSource;

    }