Пользовательский шаблон для ComboBox игнорирует использование DisplayMemberPath - PullRequest
11 голосов
/ 04 ноября 2011

Итак, я рассмотрел несколько вопросов на сайте и, похоже, не могу найти ответ.

У меня есть ComboBox. Работало просто отлично. Я решил, что мне нужно изменить внешний вид, поэтому я создаю копию шаблона ComboBox по умолчанию (это прямая копия, без изменений):

<ControlTemplate x:Key="ComboBoxControlTemplate2" 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">
                    <Microsoft_Windows_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>
                    </Microsoft_Windows_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="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                                        <Microsoft_Windows_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>
                                        </Microsoft_Windows_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>
                <ContentPresenter ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" 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>
                <Trigger Property="IsGrouping" Value="True">
                    <Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
                </Trigger>
                <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>

Теперь, когда я выбираю элемент из своего списка (который представляет собой коллекцию POCO), он отображает пространство имен и имя класса вместо значения, которое он должен.

Мои исследования и эксперименты привели меня к мысли, что проблема в том, что мой новый шаблон не использует свойство DisplayMemberPath. Я попытался установить ItemTemplate, переопределив метод OnDisplayMemberPathChanged, но это приводит к ошибкам при выборе элемента из списка.

Я также видел, как люди устанавливали ItemTemplate через XAML, но у меня есть сотни комбинированных списков, и я не хочу этого делать.

Есть ли способ использовать свойство DisplayMemberPath в моем ControlTemplate или какой-то код, который я мог бы запустить в производном элементе управления для достижения желаемого результата?

Ответы [ 5 ]

22 голосов
/ 04 ноября 2011

То есть , а не точная копия, в этом элементе отсутствует одна важная вещь:

<ContentPresenter ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
        Content="{TemplateBinding SelectionBoxItem}"
        ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}"
        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
        IsHitTestVisible="False"
        Margin="{TemplateBinding Padding}"
        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
        VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />

Возможно, вы случайно удалили его, а именно:

 ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"

Если у вас нет этого набора, DisplayMemberPath не будет работать, потому что ComboBox выбирает между шаблонами с помощью селектора шаблонов (как вы можете использовать ItemTemplate или DisplayMemberPath).

2 голосов
/ 27 января 2016

Убедитесь, что вы не пропустили элементы ContentTemplateSelector.

Для самого шаблона combox оно должно быть:

ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"

Для ItemsContainerStyle оно должно быть:

ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"        
1 голос
/ 04 ноября 2011

У меня был тот же вопрос , и оказалось, что установка DisplayMemberPath - это просто быстрый способ установки ItemTemplate в TextBlock с этим значением в нем.

Из-за этого, когда вы устанавливаете ItemTemplate, DisplayMemberPath становится бесполезным, потому что вы перезаписали TextBlock по умолчанию добавленным значением.

0 голосов
/ 06 октября 2014

Я знаю, что это старый вопрос, но я столкнулся с той же проблемой в эти дни, и я исправил ее, добавивContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"вместоContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"

0 голосов
/ 11 сентября 2014

Я столкнулся с той же проблемой, это должна быть ошибка, я попробую сообщить об этом.

Когда вы «редактируете копию» шаблона элемента управления из Visual Studio, он пропускает строку:

ContentTemplateSelector = "{TemplateBinding ItemTemplateSelector}"

Из-за чего «DisplayMemberPath» не работает должным образом.

...