2010-08-22 10 views
19

Das folgende ähnelt dem, was ich versuche, zu erreichen. Allerdings erhalte ich den FehlerGeben Sie ControlTemplate für ItemsControl.ItemContainerStyle an

Ungültiger PropertyDescriptor Wert.

auf der Vorlage Setter. Ich vermute es liegt daran, dass ich keinen TargetType für den Style angegeben habe; Ich kenne jedoch den Containertyp für ItemsControl nicht.

<ItemsControl> 
    <ItemsControl.ItemContainerStyle> 
     <Style> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate> 
         <StackPanel> 
          <TextBlock Text="Some Content Here" /> 
          <ContentPresenter /> 
          <Button Content="Edit" /> 
         </StackPanel> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </ItemsControl.ItemContainerStyle> 
    <!-- heterogenous controls --> 
    <ItemsControl.Items> 
     <Button Content="Content 1" /> 
     <TextBox Text="Content 2" /> 
     <Label Content="Content 3" /> 
    </ItemsControl.Items> 
</ItemsControl> 

Antwort

35

Sie können den Namen der Eigenschaft mit der Typenbezeichnung qualifizieren:

<Setter Property="Control.Template"> 

Der Behälter für Itemscontrol ist normalerweise ein Content, aber wenn das Kind ein UIElement ist, dann wird es kein verwenden Container. In diesem Fall sind alle untergeordneten Elemente Steuerelemente, sodass der ItemContainerStyle direkt auf sie angewendet wird. Wenn Sie ein Element außer einem UIElement hinzugefügt haben, würde dieser Setter die Control.Template-Eigenschaft für den ContentPresenter festlegen, was zwar erfolgreich wäre, aber keine Auswirkungen hat.

Eigentlich klingt es wie das, was Sie wollen, ist jedes Kind in einen Container zu wickeln, auch wenn sie bereits ein UIElement sind. Um dies zu tun, müssen Sie eine Unterklasse von ItemsControl verwenden. Sie könnten eine vorhandene wie ListBox verwenden, oder Sie könnten ItemsControl von der Unterklasse entfernen und GetContainerForItemOverride und IsItemItsOwnContainerOverride überschreiben, um die Elemente in einen eigenen Container zu verpacken. Sie können sie in ein ContentControl umbrechen und dann als TargetType für den Style verwenden.

public class CustomItemsControl 
    : ItemsControl 
{ 
    protected override DependencyObject GetContainerForItemOverride() 
    { 
     return new ContentControl(); 
    } 

    protected override bool IsItemItsOwnContainerOverride(object item) 
    { 
     // Even wrap other ContentControls 
     return false; 
    } 
} 

Sie müssen auch die Target auf dem Control so einzustellen, dass der Content an die Content-Eigenschaft binden:

<ControlTemplate TargetType="ContentControl"> 
+0

Funktioniert gut! Ich habe versucht, alles mit XAML zu machen, und nur ein paar Zeilen Code, um eine Klasse abzuleiten, machen alles glücklich, ordentlich und sauber. –

+1

"Wenn Sie ein Element außer einem UIElement hinzugefügt haben, würde dieser Setter die Control.Template-Eigenschaft für den ContentPresenter festlegen, was zwar erfolgreich wäre, aber keine Auswirkungen hat." - Ich habe lange gesucht, bevor ich diesen Tipp gefunden habe! – Daniel

2

Auch wenn Sie alles mit XAML tun mögen, können Sie ListBox einfach statt Item verwenden und einen Stil für ListBoxItem definieren:

 <ListBox ItemsSource="{Binding Elements.ListViewModels}"> 
     <ListBox.Resources> 
      <Style TargetType="ListBoxItem"> 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate TargetType="ListBoxItem"> 
          <StackPanel> 
           <TextBlock>Some Content Here</TextBlock> 
           <ContentPresenter Content="{TemplateBinding Content}" /> 
           <Button>Edit</Button> 
          </StackPanel> 
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 
      </Style> 
     </ListBox.Resources> 
     <ListBox.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel /> 
      </ItemsPanelTemplate> 
     </ListBox.ItemsPanel> 
    </ListBox> 

Beachten Sie, dass, weil ich ListBox bin mit dem Behälter ListBoxItem (im Allgemeinen der Behälter für WP F der Standardliste Steuerung wird immer das Element mit dem Namen), so dass wir schaffen einen Stil für ListBoxItem:

<Style TargetType="ListBoxItem"> 

Dann erstellen wir eine neue Control für ListBoxItem. Bitte beachten Sie, dass ContentPresenter nicht so verwendet wird, wie es immer in Artikeln und Tutorials angezeigt wird. Sie müssen diese Vorlage an die Content-Eigenschaft von ListBoxItem binden, damit der Inhalt für dieses Element angezeigt wird.

<ContentPresenter Content="{TemplateBinding Content}" /> 

Ich hatte gerade das gleiche Problem und reparierte es so. Ich wollte einige Funktionen von ListBox nicht haben (Artikelauswahl) und mit dieser Technik funktioniert die Artikelauswahl nicht mehr.