如何在具有自定义样式的组合框中显示替代文本

时间:2013-06-27 08:14:19

标签: wpf combobox

我所做的是效果如左图所示,我有一个组合框,其中包含两组数据,我想要的是当我在组合框中选择一个项目时,显示的文字看起来就像右图所示(在所选项目之前添加一些前缀),例如我在 A组中选择了项目“ 00 ”,然后显示的文字将为“ A_00 ”,如何根据我的效果实现此效果码? enter image description here

在GroupComboBoxResDic.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:helper="clr-namespace:WpfApplication3">

    <!-- Main style for ComboBox -->
    <Style x:Key="MyComboBox" TargetType="{x:Type ComboBox}">        

        <Setter Property="ItemsPanel">
            <Setter.Value>
                <ItemsPanelTemplate>
                    <WrapPanel IsItemsHost="True" Orientation="Horizontal" Width="150" Height="Auto" />
                </ItemsPanelTemplate>
            </Setter.Value>
        </Setter>

        <Setter Property="ItemTemplate">
            <Setter.Value>
                <DataTemplate>
                    <TextBlock Text="{Binding Item, Converter={StaticResource terminalToDisplayNameConverter}, Mode=OneWay}" Width="40"/>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!-- Style for ComboBoxItem -->
    <Style TargetType="{x:Type ComboBoxItem}">
        <Setter Property="Width" Value="50" />
    </Style>

    <!-- Style for ItemContainerStyle -->
    <Style x:Key="ComboBoxItemContainerStyle" TargetType="{x:Type ComboBoxItem}">
        <Setter Property="IsEnabled" Value="{Binding Available}" />
    </Style>

    <!-- DataTemplate for HeaderTemplate -->
    <DataTemplate x:Key="MyHeaderTemplate">
        <Border BorderBrush="Black" BorderThickness="2">
            <TextBlock Text="{Binding Name}" HorizontalAlignment="Stretch" Background="YellowGreen" />
        </Border>
    </DataTemplate>

</ResourceDictionary>

XAML文件

<Window x:Class="WpfApplication3.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:WpfApplication3">

    <Window.Resources>
        <ResourceDictionary Source="GroupComboBoxResDic.xaml" />
    </Window.Resources>

    <Grid>
        <ComboBox x:Name="MyComboBox1" 
                  Style="{StaticResource MyComboBox}" 
                  IsSynchronizedWithCurrentItem="False" 
                  ItemContainerStyle="{StaticResource ComboBoxItemContainerStyle}"                  
                  ItemsSource="{Binding InputsList}" Margin="293,50,104,234">
            <ComboBox.GroupStyle>
                <GroupStyle HeaderTemplate="{StaticResource MyHeaderTemplate}" />
            </ComboBox.GroupStyle>
        </ComboBox>
    </Grid>
</Window>

代码隐藏文件

public enum CategoryGroup
    {
        GroupA = 0,

        GroupB,
    }


    public class CategoryItemString
    {
        public string Item { get; set; }
        public bool Available { get; set; }

        public CategoryGroup Group { get; set; }

        public string Category
        {
            get
            {
                switch (Group)
                {
                    case CategoryGroup.GroupA:
                        return "Group A";
                    case CategoryGroup.GroupB:
                        return "Group B";
                }

                return string.Empty;
            }
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            CategoryItemString rht = obj as CategoryItemString;
            if (rht == null) return false;

            return rht.Item.Equals(this.Item) &&
                rht.Group == this.Group;
        }
    }


    public class VM : INotifyPropertyChanged
    {
        private ListCollectionView lcv;

        public VM()
        {

            List<CategoryItemString> items = new List<CategoryItemString>();

            for (int i = 0; i < 18; ++i)
            {
                items.Add(new CategoryItemString { Item = string.Format("{0:D2}", i), Available = (true), Group = CategoryGroup.GroupA });
            }

            for (int i = 0; i < 4; ++i)
            {
                items.Add(new CategoryItemString { Item = string.Format("{0:D2}", i), Available = (true), Group = CategoryGroup.GroupB });
            }

            //Need the list to be ordered by the category or you might get repeating categories
            lcv = new ListCollectionView(items.OrderBy(w => w.Category).ToList());

            //Create a group description
            lcv.GroupDescriptions.Add(new PropertyGroupDescription("Category"));
        }

        public ListCollectionView InputsList
        {
            get { return lcv; }
            set
            {
                if (lcv != value)
                {
                    lcv = value;
                    OnPropertyChanged("InputsList");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string prop)
        {
            if (this.PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
    }

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            VM vm = new VM();

            this.MyComboBox1.DataContext = vm;
        }
    }

1 个答案:

答案 0 :(得分:0)

您需要做的是修改ComboBox

的模板

首先为SelectionBox创建一个模板(ContentControl显示ComboBox模板中当前选定的项目:

<DataTemplate x:Key="mySelectionBoxItemTemplate">
    <TextBlock Text="{Binding Path=DisplayValue}" />
</DataTemplate>

然后在DisplayValue中创建CategoryItemString媒体资源:

public string DisplayValue
{
    get { return String.Format("{0}_{1}", Group, Item ); }
}

编辑ComboBox的默认模板并修改SelectionBox的ControlTemaplate,在下面的代码中查找注释以查找所做的更改:

<ControlTemplate x:Key="ComboBoxControlTemplate1" TargetType="{x:Type ComboBox}">
    <Grid x:Name="MainGrid" SnapsToDevicePixels="True">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
        </Grid.ColumnDefinitions>
        <Popup x:Name="PART_Popup" AllowsTransparency="True" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
            <Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=MainGrid}">
                <Border x:Name="DropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
                    <ScrollViewer x:Name="DropDownScrollViewer">
                        <Grid RenderOptions.ClearTypeHint="Enabled">
                            <Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
                                <Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=DropDownBorder}" Height="{Binding ActualHeight, ElementName=DropDownBorder}" Width="{Binding ActualWidth, ElementName=DropDownBorder}"/>
                            </Canvas>
                            <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        </Grid>
                    </ScrollViewer>
                </Border>
            </Themes:SystemDropShadowChrome>
        </Popup>
        <ToggleButton BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}">
            <ToggleButton.Style>
                <Style TargetType="{x:Type ToggleButton}">
                    <Setter Property="OverridesDefaultStyle" Value="True"/>
                    <Setter Property="IsTabStop" Value="False"/>
                    <Setter Property="Focusable" Value="False"/>
                    <Setter Property="ClickMode" Value="Press"/>
                    <Setter Property="Background" Value="Transparent"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ToggleButton}">
                                <Themes:ButtonChrome x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" SnapsToDevicePixels="True">
                                    <Grid HorizontalAlignment="Right" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}">
                                        <Path x:Name="Arrow" Data="M0,0L3.5,4 7,0z" Fill="Black" HorizontalAlignment="Center" Margin="3,1,0,0" VerticalAlignment="Center"/>
                                    </Grid>
                                </Themes:ButtonChrome>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsChecked" Value="True">
                                        <Setter Property="RenderPressed" TargetName="Chrome" Value="True"/>
                                    </Trigger>
                                    <Trigger Property="IsEnabled" Value="False">
                                        <Setter Property="Fill" TargetName="Arrow" Value="#FFAFAFAF"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ToggleButton.Style>
        </ToggleButton>
        <!-- Only the ContentTemplate below was changed to a static resurce-->
        <ContentPresenter ContentTemplate="{StaticResource mySelectionBoxItemTemplate}" 
                          Content="{TemplateBinding SelectionBoxItem}" 
                          ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" 
                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                          IsHitTestVisible="False" 
                          Margin="{TemplateBinding Padding}" 
                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="True">
            <Setter Property="Margin" TargetName="Shdw" Value="0,0,5,5"/>
            <Setter Property="Color" TargetName="Shdw" Value="#71000000"/>
        </Trigger>
        <Trigger Property="HasItems" Value="False">
            <Setter Property="Height" TargetName="DropDownBorder" Value="95"/>
        </Trigger>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
            <Setter Property="Background" Value="#FFF4F4F4"/>
        </Trigger>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="IsGrouping" Value="True"/>
                <Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="False"/>
            </MultiTrigger.Conditions>
            <Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
        </MultiTrigger>
        <Trigger Property="CanContentScroll" SourceName="DropDownScrollViewer" Value="False">
            <Setter Property="Canvas.Top" TargetName="OpaqueRect" Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}"/>
            <Setter Property="Canvas.Left" TargetName="OpaqueRect" Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

最后一件事 - 在MyComboBox Style

中添加上面的模板
        <Setter Property="Template" Value="{StaticResource ComboBoxControlTemplate1}" />