如何有条件地仅设置ComboBox所选项目中的文本样式?

ala*_*irs 7 wpf

我有一种情况,我需要以不同的方式对ComboBox中的所选项进行样式设置(使文本变为粗体),除非是一个值.例如,在标有"您最喜欢的原色是什么?"的下拉框中.我想有四个选项:No Preference,Red,Green,和Blue.ComboBox项只是具有默认样式的文本,没有图像或其他任何花哨的东西,而且是C#类,不包含在ComboBoxItems中.

当用户从列表中指定首选项时,我想通过将折叠列表中所选项目的文本设置为粗体来突出显示该选项.如果用户选择No Preference,字体粗细应该保持正常.

通过将ComboBox上的FontWeight属性设置为Bold,并将DataTrigger定义为,我已经实现了90%的解决方案SelectedItem != No Preference.但是,这会对ComboBox项目列表中的所有项目进行样式设置,包括下拉列表中的所有项目.我希望这些项目始终以正常的字体粗细显示.

这可能吗?

编辑

我一直在尝试@ crazyarabian用MultiTrigger设置ComboBoxItem样式的方法.样式定义是:

<Style x:Key="SelectedItemStyle">
    <Setter Property="ComboBoxItem.FontWeight" Value="Normal" />
    <Style.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="ComboBoxItem.IsSelected" Value="True" />
                <Condition Binding="{Binding IsNoPreferenceSelected,Mode=OneWay}" Value="False" />
            </MultiTrigger.Conditions>
            <Setter Property="ComboBoxItem.FontWeight" Value="Bold" />
        </MultiTrigger>
    </Style.Triggers>
</Style>
Run Code Online (Sandbox Code Playgroud)

它应用于以下DataTemplate中的ComboBox:

<DataTemplate x:Key="PrimaryColoursTemplate" DataType="{x:Type ViewModels:PrimaryColoursViewModel}">
    <ComboBox ItemsSource="{Binding PrimaryColours}" SelectedItem="{Binding SelectedPrimaryColour}"
              ItemContainerStyle="{StaticResource SelectedItemStyle}" />
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)

不幸的是,这会杀死WPF:

System.Windows.Data Error: 8 : Cannot save value from target back to source. BindingExpression:Path=IsDropDownOpen; DataItem='ComboBox' (Name=''); target element is 'ToggleButton' (Name=''); target property is 'IsChecked' (type 'Nullable`1') InvalidOperationException:'System.InvalidOperationException: Must have non-null value for 'Property'.
Run Code Online (Sandbox Code Playgroud)

应用程序死于a NullReferenceException,在上面的InvalidOperationException之后抛出(或者可能导致它,我无法解密输出).我唯一能想到的可能是导致这是在我的第二个MultiTrigger条件中解析绑定中的属性,但我根本没有得到任何绑定错误.这里是堆栈跟踪的顶部,如果有帮助的话:

InvalidOperationException:'System.InvalidOperationException: Must have non-null value for 'Property'.
   at System.Windows.Condition.Seal(ValueLookupType type)
   at System.Windows.ConditionCollection.Seal(ValueLookupType type)
   at System.Windows.MultiTrigger.Seal()
   at System.Windows.TriggerCollection.Seal()
   at System.Windows.Style.Seal()
   at System.Windows.StyleHelper.UpdateStyleCache(FrameworkElement fe, FrameworkContentElement fce, Style oldStyle, Style newStyle, Style& styleCache)
   at System.Windows.FrameworkElement.OnStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
   at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
   at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
   at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
   at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
   at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
   at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
   at System.Windows.Controls.ItemsControl.ApplyItemContainerStyle(DependencyObject container, Object item)
Run Code Online (Sandbox Code Playgroud)

Cha*_*lie 5

没有必要像所有者那样进入任何卑鄙的东西 - 我们在这里讨论的是WPF,而不是WinForms.在WinForms中,您唯一的解决方案是编写更多代码.在WPF中,我们可以使用一些非常简单的自定义模板来解决这个问题.在这个例子中,我使用了Kaxaml,一个免费的轻量级XAML编辑器.不需要代码隐藏.Kaxaml包含了许多名为Simple Styles的"入门" 样式.我使用了ComboBox Simple Style并对其进行了修改.因此虽然这看起来像很多XAML,但我真的只是从样板文件开始,并添加了几行.

您可以想到更优雅的方式来触发字体粗细变化; 我用过SelectedIndex.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <Page.Resources>
      <DataTemplate x:Key="SelectionBoxTextTemplate">
         <TextBlock FontWeight="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ComboBox}}, Path=FontWeight}" Text="{Binding}"/>
      </DataTemplate>
      <ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
         <Grid>
            <Grid.ColumnDefinitions>
               <ColumnDefinition/>
               <ColumnDefinition Width="20"/>
            </Grid.ColumnDefinitions>
            <Border
               x:Name="Border"
               Grid.ColumnSpan="2"
               Background="#C0C0C0"
               BorderBrush="#404040"
               BorderThickness="1"
               CornerRadius="2"/>
            <Border
               Grid.Column="0"
               Margin="1"
               Background="#FFFFFF"
               BorderBrush="#404040"
               BorderThickness="0,0,1,0"
               CornerRadius="2,0,0,2"/>
            <Path
               x:Name="Arrow"
               Grid.Column="1"
               HorizontalAlignment="Center"
               VerticalAlignment="Center"
               Data="M 0 0 L 4 4 L 8 0 Z"
               Fill="#404040"/>
         </Grid>
         <ControlTemplate.Triggers>
            <Trigger Property="ToggleButton.IsMouseOver" Value="true">
               <Setter TargetName="Border" Property="Background" Value="#808080"/>
            </Trigger>
            <Trigger Property="ToggleButton.IsChecked" Value="true">
               <Setter TargetName="Border" Property="Background" Value="#E0E0E0"/>
            </Trigger>
            <Trigger Property="IsEnabled" Value="False">
               <Setter TargetName="Border" Property="Background" Value="#EEEEEE"/>
               <Setter TargetName="Border" Property="BorderBrush" Value="#AAAAAA"/>
               <Setter Property="Foreground" Value="#888888"/>
               <Setter TargetName="Arrow" Property="Fill" Value="#888888"/>
            </Trigger>
         </ControlTemplate.Triggers>
      </ControlTemplate>
      <Style x:Key="{x:Type ComboBox}" TargetType="{x:Type 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="{x:Type ComboBox}">
                  <Grid>
                     <ToggleButton
                        Name="ToggleButton"
                        Grid.Column="2"
                        ClickMode="Press"
                        Focusable="false"
                        IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"
                        Template="{StaticResource ComboBoxToggleButton}">
                     </ToggleButton>
                     <ContentPresenter
                        Name="ContentSite"
                        HorizontalAlignment="Left"
                        Margin="3,3,23,3"
                        VerticalAlignment="Center"
                        Content="{TemplateBinding SelectionBoxItem}"
                        ContentTemplate="{StaticResource SelectionBoxTextTemplate}"
                        ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
                        IsHitTestVisible="False"/>
                     <TextBox
                        x:Name="PART_EditableTextBox"
                        HorizontalAlignment="Left"
                        Margin="3,3,23,3"
                        VerticalAlignment="Center"
                        Background="Transparent"
                        Focusable="False"
                        IsReadOnly="{TemplateBinding IsReadOnly}"
                        Style="{x:Null}"
                        Visibility="Hidden"/>
                     <Popup
                        Name="Popup"
                        AllowsTransparency="True"
                        Focusable="False"
                        IsOpen="{TemplateBinding IsDropDownOpen}"
                        Placement="Bottom"
                        PopupAnimation="Slide">
                        <Grid
                           Name="DropDown"
                           MaxHeight="{TemplateBinding MaxDropDownHeight}"
                           MinWidth="{TemplateBinding ActualWidth}"
                           SnapsToDevicePixels="True">
                           <Border
                              x:Name="DropDownBorder"
                              Background="#FFFFFF"
                              BorderBrush="#888888"
                              BorderThickness="1"/>
                           <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="#888888"/>
                     </Trigger>
                     <Trigger Property="IsGrouping" Value="true">
                        <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                     </Trigger>
                     <Trigger Property="Popup.AllowsTransparency" SourceName="Popup" Value="true">
                        <Setter TargetName="DropDownBorder" Property="CornerRadius" Value="4"/>
                        <Setter TargetName="DropDownBorder" Property="Margin" Value="0,2,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>
                     <Trigger Property="SelectedIndex" Value="1">
                        <Setter Property="FontWeight" Value="Bold"/>
                     </Trigger>
                     <Trigger Property="SelectedIndex" Value="2">
                        <Setter Property="FontWeight" Value="Bold"/>
                     </Trigger>
                     <Trigger Property="SelectedIndex" Value="3">
                        <Setter Property="FontWeight" Value="Bold"/>
                     </Trigger>
                  </ControlTemplate.Triggers>
               </ControlTemplate>
            </Setter.Value>
         </Setter>
      </Style>
      <Style x:Key="{x:Type ComboBoxItem}" TargetType="{x:Type ComboBoxItem}">
         <Setter Property="SnapsToDevicePixels" Value="true"/>
         <Setter Property="OverridesDefaultStyle" Value="true"/>
         <Setter Property="FontWeight" Value="Normal"/>
         <Setter Property="Template">
            <Setter.Value>
               <ControlTemplate TargetType="{x:Type ComboBoxItem}">
                  <Border Name="Border" Padding="2" SnapsToDevicePixels="true">
                     <ContentPresenter/>
                  </Border>
                  <ControlTemplate.Triggers>
                     <Trigger Property="IsHighlighted" Value="true">
                        <Setter TargetName="Border" Property="Background" Value="#DDDDDD"/>
                     </Trigger>
                     <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="#888888"/>
                     </Trigger>
                  </ControlTemplate.Triggers>
               </ControlTemplate>
            </Setter.Value>
         </Setter>
      </Style>
   </Page.Resources>
   <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
      <TextBlock Margin="5" Text="What is your favorite primary colour?"/>
      <ComboBox Width="150" SelectedIndex="0">
         <ComboBoxItem>No Preference</ComboBoxItem>
         <ComboBoxItem>Red</ComboBoxItem>
         <ComboBoxItem>Green</ComboBoxItem>
         <ComboBoxItem>Blue</ComboBoxItem>
      </ComboBox>
   </StackPanel>
</Page>
Run Code Online (Sandbox Code Playgroud)

我使用in 的ContentTemplate属性来添加自定义数据模板().这抓住了从祖先组合框中.然后我为各个项目添加了一个模板,强制它们达到正常的字体粗细.这得到了您正在寻找的结果:ContentPresenterComboBoxSelectionBoxTextTemplateTextBlockFontWeight

在此输入图像描述