2011-11-04 294 views
9

所以我已經在網站上經歷了幾個問題,而且我似乎無法找到答案。組合框的自定義模板忽略使用DisplayMemberPath

我有一個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屬性。我試圖通過重寫OnDisplayMemberPathChanged方法來設置ItemTemplate,但是當我從列表中選擇一個項目時會導致錯誤。

我也看到人們通過XAML設置了ItemTemplate,但我有數百個組合框,我不想這樣做。

有沒有一些方法可以利用我的ControlTemplate中的DisplayMemberPath屬性,或者我可以在派生控件中運行一些代碼來實現我想要的結果?

回答

19

也就是說完全相同的副本,一個關鍵的東西是缺少這個元素:

<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使用模板選擇器在模板之間進行選擇(因爲您可以使用ItemTemplateDisplayMemberPath)。

+0

夥計!這完全奏效。儘管我從未看到過這種解決方案,但我從未產生過100%的積極態度。我已經完成了這個過程3到4次,並檢查了幾十個有同樣問題的人。這完全是微軟方面的一個錯誤......謝謝! – CamronBute

+0

既然喜悅消退了,我必須問問你是怎麼想出來的。你用什麼來生成模板副本? – CamronBute

+3

@CamronBute:嗯,我總是有默認的模板,你可以[在MSDN](http://msdn.microsoft.com/en-us/library/aa970773.aspx)('Default WPF Themes'鏈接)手,所以我檢查了一下,看看事情是如何綁定的。不難看出,這個ContentPresenter是所選項目的關鍵組件,所以如果出現錯誤,它應該在那裏,那麼我只需要將它與您的項目進行比較,以查看此屬性是否丟失。我還測試了自己移除該屬性的效果,並且如預期的那樣僅顯示了類型名稱。 –

1

我有same question,事實證明設置DisplayMemberPath只是將ItemTemplate設置爲具有該值的TextBlock的快捷方式。

因此,當您設置ItemTemplate時,則DisplayMemberPath變得無用,因爲您已使用它添加的值覆蓋了默認TextBlock。

+0

檢查上面的答案。我在相關問題中看到了您的問題,但上述解決方案適用於我!無論如何,謝謝:) – CamronBute

+0

我使用了H.B.的解決方案。但隨着這個答案,嘗試'ContentTemplate =「{TemplateBinding ItemTemplate}」'也工作 - 雖然我沒有打擾留下足夠長的時間來測試任何副作用。 – OhBeWise

0

我遇到了同樣的問題,這應該是一個錯誤,我會嘗試報告它。

當 「編輯複製」 從Visual Studio控件模板的,它忽略了行:

ContentTemplateSelector = 「{TemplateBinding ItemTemplateSelector}」

造成 「的DisplayMemberPath」 不能正常工作。

0

我知道這是一個老問題,但我在這些日子裏所面臨的同樣的問題,我固定它添加

ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"

而不是

ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"

1

確保您不會錯過ContentTemplateSelector元素。

對於COMBOX模板本身應該是:

ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" 

對於ItemsContainerStyle應該是:

ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"