Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF组合框:文本框和下拉列表中的不同模板_C#_Wpf_Xaml_Combobox - Fatal编程技术网

C# WPF组合框:文本框和下拉列表中的不同模板

C# WPF组合框:文本框和下拉列表中的不同模板,c#,wpf,xaml,combobox,C#,Wpf,Xaml,Combobox,这是我的组合框 <ComboBox Height="45" HorizontalAlignment="Left" Margin="184,66,0,0" Name="ComboBox1" VerticalAlignment="Top" Width="216"> <ComboBox.ItemTemplate> <DataTemplate> <StackPanel Orienta

这是我的组合框

    <ComboBox Height="45" HorizontalAlignment="Left" Margin="184,66,0,0" Name="ComboBox1" VerticalAlignment="Top" Width="216">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <Label Content="{Binding FullName}" Width="150" />
                    <Label Content="{Binding Title}" Width="100"/>
                    <Label Content="{Binding BranchName}" />
                </StackPanel>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>


如何更改它,使组合框的文本框部分仅显示全名,而下拉部分中仍显示所有三列?

不幸的是,
SelectionBoxItemTemplate
是只读属性,因此我们需要做更多的工作。通过将
ItemTemplate
作为选中项目时的显示方式,您可以编辑
ItemContainerStyle
以提供包含要显示的其他字段的
ControlTemplate

<ComboBox Height="45" HorizontalAlignment="Left" Margin="184,66,0,0" Name="ComboBox1" VerticalAlignment="Top" Width="216">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <Label Content="{Binding FullName}" Width="150" />
        </DataTemplate>
    </ComboBox.ItemTemplate>
    <ComboBox.ItemContainerStyle>
        <Style TargetType="{x:Type ComboBoxItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ComboBoxItem}">
                        <Border x:Name="Bd"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Background="{TemplateBinding Background}">
                            <StackPanel Orientation="Horizontal">
                                <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                                <Label Content="{Binding Title}" Width="100"/>
                                <Label Content="{Binding BranchName}" />
                            </StackPanel>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsHighlighted" Value="True">
                                <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
                                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ComboBox.ItemContainerStyle>
</ComboBox>


对于
ComboBoxItem
模板,我刚刚修改了默认的一个,因此它应该是功能齐全的。

如果ComboBox的IsEdit属性设置为True,您可以将ComboBox的“TextSearch.TextPath”属性设置为要显示的属性名称。因此,在你的情况下:

<ComboBox IsEditable="True" TextSearch.TextPath="FullName" .../>

我没有使用只读SelectionBoxItemTemplate属性,而是创建了一个新的(附加的、可写的)属性,并在我的样式中使用了该属性。我还为我的样式添加了一个触发器,以不破坏所有未使用新附加属性的组合框

像这样使用它:

<ComboBox ItemsSource="{Binding ...}" SelectedItem="{Binding ..., Mode=TwoWay}">
    <controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate>
        <DataTemplate DataType="{x:Type ...}">
            ... Template for the selection box ...
        </DataTemplate>
    </controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate>
    <ComboBox.ItemTemplate>
        <DataTemplate DataType="{x:Type ...}">
            ... Template for the popup ...
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>
如果设置了SelectionBoxAltTemplate attached属性,请更改组合框样式以使用该属性(或者因为我无法将触发器设置为“not null”,如果附加的属性为null,则将其设置回默认SelectionBoxItemTemplate):

组合框样式的ControlTemplate中的ContentPresenter:

<ContentPresenter Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate}" />

和触发器,以提供对ComboBox的向后兼容性,而无需附加属性:

<ControlTemplate.Triggers>
    <Trigger Property="controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate" Value="{x:Null}">
        <Setter Property="ContentTemplate" Value="{Binding SelectionBoxItemTemplate, RelativeSource={RelativeSource TemplatedParent}}" TargetName="ContentSite" />
    </Trigger>
    ...
</ControlTemplate.Triggers>

...
完整样式:

<Style x:Key="{x:Type ComboBox}" TargetType="{x:Type ComboBox}">
    <Setter Property="SnapsToDevicePixels" Value="true" />
    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
    <Setter Property="VerticalContentAlignment" Value="Center" />
    <Setter Property="FontSize" Value="12" />
    <Setter Property="Background" Value="{StaticResource ComboBoxBackground}"/>
    <Setter Property="BorderBrush" Value="{StaticResource ComboBoxBorder}"/>
    <Setter Property="Margin" Value="6"/>
    <Setter Property="Padding" Value="3,3,5,3"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ComboBox}">
                <Grid>
                    <Grid.ColumnDefinitions>                    
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <Border Name="Border" Grid.ColumnSpan="2" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/>
                    <ToggleButton Name="ToggleButton2" Focusable="False" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" Grid.ColumnSpan="2" Background="Transparent"/>
                    <!-- Allows clicking anywhere on the combobox, not only the visible button on the right -->
                    <ToggleButton Focusable="false" Grid.Column="1" x:Name="ToggleButton" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" Style="{StaticResource ComboBoxToggleButton}"/>
                    <ContentPresenter HorizontalAlignment="Left" Margin="{TemplateBinding Control.Padding}" x:Name="ContentSite" VerticalAlignment="Center" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" IsHitTestVisible="False" />

                    <TextBox Visibility="Hidden"  HorizontalAlignment="Left" Margin="{TemplateBinding Control.Padding}" x:Name="PART_EditableTextBox" Style="{x:Null}" VerticalAlignment="Center" Focusable="True" Background="Transparent"  />

                    <Popup IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" x:Name="Popup" Focusable="False" AllowsTransparency="True" PopupAnimation="Slide">
                        <Grid MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding ActualWidth}" x:Name="DropDown" SnapsToDevicePixels="True">
                            <Border x:Name="DropDownBorder" Background="{StaticResource ComboBoxBackground}" BorderBrush="{StaticResource ComboBoxBorder}" BorderThickness="1" Padding="0,4">
                                <ScrollViewer SnapsToDevicePixels="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True" Style="{x:Null}" >
                                    <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained"/>
                                </ScrollViewer>
                            </Border>
                        </Grid>
                    </Popup>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate" Value="{x:Null}">
                        <Setter Property="ContentTemplate" Value="{Binding SelectionBoxItemTemplate, RelativeSource={RelativeSource TemplatedParent}}" TargetName="ContentSite" />
                    </Trigger>
                    <Trigger Property="HasItems" Value="false">
                        <Setter Property="MinHeight" Value="95" TargetName="DropDownBorder" />
                    </Trigger>
                    <Trigger Property="IsGrouping" Value="true">
                        <Setter Property="ScrollViewer.CanContentScroll" Value="false" />
                    </Trigger>
                    <Trigger Property="IsEditable" Value="true">
                        <Setter Property="IsTabStop" Value="false" />
                        <Setter Property="Visibility" Value="Visible" TargetName="PART_EditableTextBox" />
                        <Setter Property="Visibility" Value="Hidden" TargetName="ContentSite" />
                    </Trigger>

                    <Trigger Property="IsMouseOver" Value="true" SourceName="ToggleButton2">
                        <Setter Property="Background" Value="{StaticResource ComboBoxMouseOver}" />
                    </Trigger>
                    <Trigger Property="HasItems" Value="False">
                        <Setter Property="IsEnabled" Value="False"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>


但是,这可能不适用于ItemTemplateSelectors,仅适用于一个模板-但您可以轻松添加附加属性“SelectionBoxAltTemplateSelector”,该属性提供选择器并将其传递给样式。

如果您不想更改组合框样式,这里有一个很好的答案回答您的问题:


它在DataTemplate中使用一个触发器,用于查看视觉树中是否有ComboBoxItem,而在选择框中则不是这样。

您可以覆盖ComboxBox并直接更改SelectionBoxItemTemplate

public class SelectionComboBox : ComboBox
{
    #region Properties

    #region Dependency Properties
    public DataTemplate AltSelectionBoxItemTemplate
    {
        get { return (DataTemplate)GetValue(AltSelectionBoxItemTemplateProperty); }
        set { SetValue(AltSelectionBoxItemTemplateProperty, value); }
    }

    public static readonly DependencyProperty AltSelectionBoxItemTemplateProperty =
        DependencyProperty.Register("AltSelectionBoxItemTemplate", typeof(DataTemplate), typeof(SelectionComboBox), new UIPropertyMetadata(null, (s, e) =>
        {
            // For new changes...
            if ((s is SelectionComboBox) && ((SelectionComboBox)s).Presenter != null && (e.NewValue is DataTemplate))
                ((SelectionComboBox)s).Presenter.ContentTemplate = (DataTemplate)e.NewValue;

            // Set the new value
            ((SelectionComboBox)s).AltSelectionBoxItemTemplate = (DataTemplate)e.NewValue;
        }));
    #endregion

    #region Internals

    #region Elements
    ContentPresenter Presenter { get; set; }
    #endregion

    #endregion

    #endregion

    #region Constructors
    #endregion

    #region Methods

    #region Overrides
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        Presenter = this.GetTemplateChild("contentPresenter") as ContentPresenter;

        // Directly Set the selected item template
        if (AltSelectionBoxItemTemplate != null) Presenter.ContentTemplate = AltSelectionBoxItemTemplate;
    }
    #endregion

    #endregion

}
定义控件后,可以设置其样式

<controls:SelectionComboBox ItemsSource="{Binding ...}" SelectedItem="{Binding ..., Mode=TwoWay}">
    <controls:SelectionComboBox.AltSelectionBoxItemTemplate>
        <DataTemplate>
            <!-- My Template Goes Here... -->
        </DataTemplate>
    </controls:SelectionComboBox.AltSelectionBoxItemTemplate>
</controls:SelectionComboBox>


我需要很长时间才能完全理解您所做的工作,但它确实像广告中所说的那样有效。虽然已经有几年了,但这个答案对我很有用+1“中断”文本搜索是什么意思?
<controls:SelectionComboBox ItemsSource="{Binding ...}" SelectedItem="{Binding ..., Mode=TwoWay}">
    <controls:SelectionComboBox.AltSelectionBoxItemTemplate>
        <DataTemplate>
            <!-- My Template Goes Here... -->
        </DataTemplate>
    </controls:SelectionComboBox.AltSelectionBoxItemTemplate>
</controls:SelectionComboBox>