2011-11-04 10 views
9

He recibido varias preguntas en el sitio y parece que no puedo encontrar la respuesta.La plantilla personalizada para ComboBox ignora el uso de DisplayMemberPath

Tengo ComboBox. Funcionaba bien. Decido que necesito para reformar la apariencia, por lo que se crea una copia de la plantilla ComboBox por defecto (esto es una copia directa, sin necesidad de modificaciones):

<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> 

Ahora, cuando seleccione un elemento de mi lista (que es una colección de POCO), muestra el espacio de nombre y el nombre de clase en lugar del valor que se supone que debe.

Mi investigación y experimentación me han llevado a creer que el problema es que mi nueva plantilla no hace uso de la propiedad DisplayMemberPath. Traté de establecer un ItemTemplate anulando el método OnDisplayMemberPathChanged, pero eso produce errores cuando selecciono un elemento de la lista.

También he visto personas configurar el ItemTemplate a través de XAML, pero tengo cientos de cuadros combinados, y no quiero hacer eso.

¿Hay alguna manera de utilizar la propiedad DisplayMemberPath en mi ControlTemplate, o algún código que pueda ejecutar en un control derivado para lograr el resultado deseado?

Respuesta

19

Eso es no una copia exacta, una cosa fundamental que falta en este elemento:

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

Tal vez has borrado accidentalmente, a saber:

ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" 

Si no tiene este establecer el DisplayMemberPath no funcionará porque el ComboBox selecciona entre plantillas usando un selector de plantilla (como puede usar ItemTemplate o).

+0

¡Amigo! Eso funcionó por completo. Sin embargo, nunca vi esa solución, y estoy 100% seguro de que nunca se generó. He realizado este proceso 3 o 4 veces y he comprobado la cantidad de personas con el mismo problema. Esto debe ser totalmente un error del lado de Microsoft ... ¡Gracias! – CamronBute

+0

Ahora que la alegría ha disminuido, debo preguntar cómo lo descubrió. ¿Qué estás usando para generar copias de plantilla? – CamronBute

+3

@CamronBute: Bueno, siempre tengo las plantillas predeterminadas que puede obtener [en MSDN] (http://msdn.microsoft.com/en-us/library/aa970773.aspx) (enlace 'Temas predeterminados de WPF') en mano, así que lo verifiqué para ver cómo están las cosas atadas. No es difícil ver que este 'ContentPresenter' es el componente clave para el elemento seleccionado, así que si hay un error debería estar allí, entonces solo necesitaba compararlo con el suyo para ver que esta propiedad faltaba. También probé el efecto de eliminar esa propiedad y, como era de esperar, solo mostró el nombre del tipo. –

1

tuve la same question, y resulta que el establecimiento de las DisplayMemberPath es simplemente una forma de acceso directo para ajustar el ItemTemplate a un TextBlock con ese valor en ella.

Debido a esto, cuando configura ItemTemplate, entonces DisplayMemberPath se vuelve inútil porque ha sobrescrito el valor predeterminado de TextBlock con el valor agregado.

+0

Verificar la respuesta anterior. Vi su problema en una pregunta relacionada, ¡pero la solución anterior funciona para mí! De todos modos, gracias :) – CamronBute

+0

Utilicé la solución de H.B. pero como consecuencia de esta respuesta, también intenté con 'ContentTemplate =" {TemplateBinding ItemTemplate} '', aunque no me molesté en dejarlo el tiempo suficiente para probar los efectos secundarios. – OhBeWise

0

Me encontré con el mismo problema, esto debería ser un error, intentaré informarlo.

Cuando "editar una copia" de la plantilla de control desde Visual Studio, se echa de menos la línea:

ContentTemplateSelector = "{} TemplateBinding ItemTemplateSelector"

que causó "DisplayMemberPath" no funciona correctamente.

0

Sé que esto es una vieja pregunta, pero me enfrenté al mismo problema en estos días y lo arreglé añadiendo

ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"

en lugar de

ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"

1

Asegúrese de que no se echa en falta la Elementos de ContentTemplateSelector.

Para la plantilla combox sí que debe ser:

ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" 

Para el ItemsContainerStyle que debe ser:

ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"   
Cuestiones relacionadas