WPF - 根据项目模板更改组合框样式

Posted

技术标签:

【中文标题】WPF - 根据项目模板更改组合框样式【英文标题】:WPF - change combobox style depending on itemtemplate 【发布时间】:2019-03-07 02:36:18 【问题描述】:

我需要创建一个组合,当它的下拉关闭时将显示一个简单的文本(枚举)值。但是当用户点击下拉菜单时,它应该在组合框项目中显示一个包含更多信息的复杂数据模板。

我创建了两个数据模板,用于在关闭或打开下拉菜单时显示不同的信息。

<DataTemplate x:Key="DropDownOpenedTemplate">
        <ContentControl Content="Binding">
            <ContentControl.Style>
                <Style TargetType="x:Type ContentControl">
                    <!-- Complex template -->
                    <Setter Property="ContentTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <DockPanel >
                                    <Image Width="100" DockPanel.Dock="Left" Stretch="Uniform" Source="Binding ImageUri" 
                                            VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,15,0" />
                                    <StackPanel DockPanel.Dock="Right" Orientation="Vertical">
                                        <TextBlock Text="Binding Name" VerticalAlignment="Center" HorizontalAlignment="Left" FontStyle="Italic" FontWeight="Bold" Margin="10,0,0,5"/>
                                        <TextBlock Text="Binding Description" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="25,0,0,0"/>
                                    </StackPanel>
                                </DockPanel>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ContentControl.Style>
        </ContentControl>
    </DataTemplate>
    <DataTemplate x:Key="DropDownClosedTemplate" >
        <ContentControl Content="Binding">
            <ContentControl.Style>
                <Style TargetType="x:Type ContentControl">
                    <!-- default template -->
                    <Setter Property="ContentTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <TextBlock Text="Binding Name" HorizontalAlignment="Stretch"  />
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ContentControl.Style>
        </ContentControl>
    </DataTemplate>

然后我创建了一个模板选择器,它将覆盖 SelectTemplate 方法

public override DataTemplate SelectTemplate(object item, DependencyObject container)
    
        ContentPresenter presenter = (ContentPresenter)container;

        FrameworkElement elemnt = container as FrameworkElement;

        while (container != null)
        
            container = VisualTreeHelper.GetParent(container);
            if (container is ComboBoxItem)
                return (DataTemplate)presenter.FindResource("DropDownOpenedTemplate"); ;
        
        return (DataTemplate)presenter.FindResource("DropDownClosedTemplate");

    

此功能工作正常。但现在我需要根据使用的模板格式化样式。为简化起见,我需要在选择 dropdownclosetemplate 时组合框的背景颜色为蓝色,选择 dropdownopenedtemplate 时为黄色,并且所选项目的背景应为红色。

<ComboBox x:Name="spComboBox" Grid.Row="1"
                  Grid.Column="1"
                  Width="200"
                  Margin="30"
              Background="Blue"
                  HorizontalAlignment="Center"
                  VerticalAlignment="Center"
                  ItemsSource="Binding ModeList" 
                  SelectedValue="Binding SelectedMode, Mode=TwoWay" 
                  ScrollViewer.CanContentScroll="False" 
                  ItemTemplateSelector="StaticResource ComboBoxItemTemplateSelector">
        <ComboBox.ItemContainerStyle>
            <Style TargetType="ComboBoxItem">
                <Setter Property="Background" Value="Yellow"/>
                <Style.Triggers>
                    <DataTrigger Binding="Binding Path=IsDropDownOpen, RelativeSource=RelativeSource TemplatedParent" Value="False">
                        <Setter Property="Background" Value="Blue" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ComboBox.ItemContainerStyle>

    </ComboBox>

我只能看到黄色,但不能在选择dropdownopededtemplate时更改DropdowncloseTemplate的样式,并选择DropdownopedTemplate时。

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

如果您不需要使用 relativesource= 而是使用 elementname=spComboBox,您可以轻松地进行绑定。但是,如果我正确理解了您的三个状态,我认为您根本不需要它(如果没有,请具体说明,也许带有显示所有状态的图像)。我添加了一个文本框来显示这种绑定。它也适用于数据触发器。但是我认为,如果您想对其进行测试,则应将其与 True 进行比较,而不是像您的示例中那样与 false 进行比较。

这是我的解决方案:

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   >
<StackPanel>
        <ComboBox x:Name="spComboBox" Grid.Row="1"
                  Grid.Column="1"
                  Width="200"
                  Margin="30"
                  Background="Blue"
                  HorizontalAlignment="Center"
                  VerticalAlignment="Center"
                  ScrollViewer.CanContentScroll="False" >
            <ComboBoxItem Name="cbi1">Item1</ComboBoxItem>
            <ComboBoxItem Name="cbi2">Item2</ComboBoxItem>
            <ComboBoxItem Name="cbi3">Item3</ComboBoxItem>
            <ComboBox.ItemContainerStyle>
                <Style TargetType="ComboBoxItem">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="ComboBoxItem">
                                <Border x:Name="border" BorderThickness="1" Padding="3" Background="Yellow">
                                    <ContentPresenter/>
                                </Border>

                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsSelected" Value="True">
                                        <Setter TargetName="border" Property="Background" Value="Red"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
           </ComboBox.ItemContainerStyle>

        </ComboBox>
        <TextBlock Text="Binding ElementName=spComboBox, Path=IsDropDownOpen"></TextBlock>
    </StackPanel>
    </Window>

当没有选择任何内容时,它显示蓝色。当你打开下拉菜单时,所有项目都是黄色的,如果你选择一个,背景=红色(虽然不容易立即看到,因为光标直接设置到它,隐藏颜色,但你会看到它是红色的,一旦你移动光标)

关闭状态下的背景色,this answer should help

【讨论】:

感谢简的回复。当存在模板选择器时,我无法通过仅更改背景属性将组合框的背景颜色更改为蓝色。使用 IsSelected 属性而不是 IsDropDownOpen 属性是正确的(我在代码中犯了一个错误),但即使将属性更改为 IsSelected,代码也不会更改所选组合框项的颜色。 @Dhan 你能检查一下 isselected 是否适用于我的代码位吗?来源:dotnetcurry.com/wpf/1211/wpf-items-control-advanced-topic @Dhan 我认为我答案中的最后一个链接应该可以解决最后一个问题,尽管它远非一个简单的解决方案

以上是关于WPF - 根据项目模板更改组合框样式的主要内容,如果未能解决你的问题,请参考以下文章

WPF 组合框禁用背景颜色

WPF:在不知道项目的情况下更改组合框的字体大小

WPF:尝试根据组合框中的选择更改可见性

在 wpf 中应用样式时,用户控件内的组合框消失

用于选定值和搜索功能的 wpf 组合框项目模板

在使用ItemContainerGenerator进行自定义时,WPF ComboBox在第二次打开之前不会更新项目