2011-11-04 22 views
9

. Przeszedłem przez kilka pytań na stronie i nie mogę znaleźć odpowiedzi.Niestandardowy szablon dla ComboBox ignoruje użycie DisplayMemberPath

Mam ComboBox. To działało dobrze. Zdecyduję muszę remont wygląd, więc utworzyć kopię szablonu domyślnego kombi (jest to proste kopiowanie, żadne modyfikacje):

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

Teraz, kiedy wybrać element z mojej listy (co jest zbiór POCO), wyświetla nazwę przestrzeni i nazwę klasy zamiast wartości, którą powinien.

Moje badania i eksperymenty doprowadziły mnie do przekonania, że ​​problem polega na tym, że mój nowy szablon nie korzysta z właściwości DisplayMemberPath. Próbowałem ustawić ItemTemplate przez przesłonięcie metody OnDisplayMemberPathChanged, ale to powoduje błędy, gdy wybieram element z listy.

Widziałem również ludzi ustawić ItemTemplate przez XAML, ale mam setki comboboxes i nie chcę tego zrobić.

Czy istnieje jakiś sposób wykorzystania właściwości DisplayMemberPath w mojej klasie ControlTemplate lub kodu, który mógłbym uruchomić w kontrolce pochodnej, aby osiągnąć pożądany wynik?

Odpowiedz

19

To nie dokładną kopią, jedna kluczowa rzecz, brakuje w tym elemencie:

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

Może przypadkowo usunięta, a mianowicie:

ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" 

Jeśli nie masz tego ustawienie DisplayMemberPath nie będzie działać, ponieważ ComboBox wybiera między szablonami za pomocą selektora szablonów (jak można użyć ItemTemplate lub DisplayMemberPath).

+0

Koleś! To całkowicie działało. Jednak nigdy nie widziałem takiego rozwiązania i jestem w 100% przekonany, że nigdy nie został wygenerowany. Zrobiłem ten proces 3 lub 4 razy i sprawdziłem dziesiątki osób z tym samym problemem. To musi być całkowicie błąd po stronie Microsoftu ... Dziękuję! – CamronBute

+0

Teraz, gdy radość ustąpiła, muszę zapytać, jak to rozgryzłeś. Czego używasz do generowania kopii szablonów? – CamronBute

+3

@CamronBute: Cóż, zawsze mam domyślne szablony, które można uzyskać [w MSDN] (http://msdn.microsoft.com/en-us/library/aa970773.aspx) ("Domyślne motywy WPF") pod adresem Ręka, więc sprawdziłem, żeby zobaczyć, jak rzeczy są powiązane. Nie jest trudno zauważyć, że ten "ContentPresenter" jest kluczowym komponentem dla wybranego elementu, więc jeśli wystąpił błąd, powinien tam być, a następnie wystarczy porównać go z twoim, aby zobaczyć, że tej właściwości nie było. Przetestowałem również efekt usunięcia tej właściwości i zgodnie z oczekiwaniami pokazała ona jedynie nazwę typu. –

1

miałem same question, a okazuje się ustawienie DisplayMemberPath to po prostu skrót sposób na ustawienie ItemTemplate Do TextBlock z tej wartości w nim.

Z tego powodu po ustawieniu ItemTemplate następnie DisplayMemberPath staje się bezużyteczne, ponieważ nadpisałeś domyślny TextBlock z wartością, którą dodaje.

+0

Sprawdź odpowiedzi powyżej. Widziałem twój problem w pokrewnym pytaniu, ale powyższe rozwiązanie działa dla mnie! Mimo to dziękuję :) – CamronBute

+0

Użyłem rozwiązania autorstwa H.B. ale w wyniku tej odpowiedzi, próba "ContentTemplate =" {TemplateBinding ItemTemplate} "również zadziałała - chociaż nie zadałem sobie trudu pozostawienia go na tyle długo, aby przetestować wszelkie efekty uboczne. – OhBeWise

0

Spotkałem ten sam problem, powinien to być błąd, spróbuję go zgłosić.

Kiedy "edytować kopię" wzoru sterującego z Visual Studio, to strzela wiersz:

ContentTemplateSelector = "{TemplateBinding ItemTemplateSelector}"

który spowodował "DisplayMemberPath" nie działa prawidłowo.

0

wiem, jest to stara sprawa, ale w obliczu tego samego problemu w tych dniach i naprawiłem to dodanie

ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"

zamiast

ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"

1

Upewnij się, że nie brakuje Elementy ContentTemplateSelector.

szablonu Combox sam powinien to być:

ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" 

Dla ItemsContainerStyle powinno być:

ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"   
Powiązane problemy