WPF:简单的MSWord颜色选择器按钮

时间:2014-09-24 20:44:53

标签: wpf button combobox

是否有一种快速简便的方法来实现像MS Word中那样的颜色选择按钮?

我希望用户在下拉列表中从多种预定义颜色中进行选择。按钮关闭时,应显示所选颜色。当用户单击该按钮时,应触发事件或命令。我想使用一个按钮实例在RichTextBox中设置文本颜色,另一个用于设置背景颜色(类似于MS Word)。

我的第一种方法是使用带有DataTemplate的ComboBox,其中包含一个按钮。 这不起作用:当用户单击它时,不会触发按钮的命令。而是打开ComboBox的下拉列表。我不知道确切的原因,但可能是ComboBox默认模板中的IsHitTestVisible = false属性?请参阅:http://msdn.microsoft.com/en-us/library/dd334408%28v=vs.95%29.aspx

<UserControl x:Class="MyBrushPicker"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    mc:Ignorable="d"              
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    Height="Auto" Width="Auto" MinWidth="50">
    <UserControl.Resources>

        <!--
        Provide two different DataTemplates:
        - SelectionBoxTemplate is used to display the selected color when the ComboBox is closed.
          It contains a button which should be clickable (does not work).
        - NormalItemTemplate is used to display a color in the opened ComboBox popup.
        See:
        http://stackoverflow.com/questions/2214696/wpf-how-to-customize-selectionboxitem-in-combobox 
        -->

        <DataTemplate x:Key="NormalItemTemplate">
            <Border Height="44" Width="44" Margin="3,3,3,3" BorderThickness="1" BorderBrush="Black" Background="{Binding Mode=OneWay}"/>
        </DataTemplate>

        <DataTemplate x:Key="SelectionBoxTemplate">
            <!-- This button cannot be clicked: PreviewMouseDown and Button_Click events are never triggered. -->
            <Button Click="Button_Click" PreviewMouseDown="Button_PreviewMouseDown">
                <Border Height="44" Width="44" Margin="3,3,3,3" BorderThickness="1" BorderBrush="Black" Background="{Binding Mode=OneWay}"/>
            </Button>
        </DataTemplate>

        <DataTemplate x:Key="CombinedTemplate">

            <ContentPresenter x:Name="Presenter"
                   Content="{Binding}"                                  
                   ContentTemplate="{StaticResource NormalItemTemplate}" />

            <DataTemplate.Triggers>
                <DataTrigger
                    Binding="{Binding RelativeSource={RelativeSource FindAncestor,ComboBoxItem,1}}"
                    Value="{x:Null}">

                    <Setter TargetName="Presenter" Property="ContentTemplate"
                        Value="{StaticResource SelectionBoxTemplate}" />
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </UserControl.Resources>

    <ComboBox IsReadOnly="True" IsEditable="False" 
              ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=SelectableBrushes, Mode=OneWay}" 
              SelectedItem="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=SelectedBrush, Mode=TwoWay}"
              ScrollViewer.VerticalScrollBarVisibility="Auto"
              MinHeight="50"
              MaxDropDownHeight="200"
              ItemTemplate="{StaticResource CombinedTemplate}"
              >

        <ComboBox.Resources>
            <Style TargetType="ComboBox">
                <Setter Property="ItemsPanel">
                    <Setter.Value>
                        <ItemsPanelTemplate>
                            <WrapPanel IsItemsHost="True" Orientation="Horizontal" Width="200" />
                        </ItemsPanelTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <Style TargetType="ComboBoxItem">
                <Setter Property="Width" Value="50" />
                <Setter Property="Height" Value="50" />
            </Style>
        </ComboBox.Resources>

    </ComboBox>
</UserControl>

有没有办法让按钮正常工作? 还有更好的方法吗?

编辑:使用Snoop工具显示,ComboBox中未命名的ContentPresenter的IsHitTestVisible属性实际上设置为false(ValueSource:ParentTemplate)。如果我使用Snoop将此属性设置为true,则该按钮变为可单击。

我可以从样式更改此属性吗? 至少,以下内容不起作用:

<ComboBox.Resources>
    <Style TargetType="ContentPresenter">
        <Setter Property="IsHitTestVisible" Value="True" />
    </Style>
</ComboBox.Resources>

1 个答案:

答案 0 :(得分:2)

假设您不仅仅是将此作为一种学习练习(使图书馆毫无意义)......

请看一下: Extended WPF Toolkit - Color Picker

我以前使用过简单的即插即用WPF颜色选择器,它可以很好地解决你的问题。