2010-08-25 7 views
22

Ich habe einige Artikel gesehen, die zeigen, wie AlternationIndex mit ListBox es oder ListView s zu verwenden, aber ich hatte ein paar Stunden versucht, wechselnde Hintergrundfarben auf der Basis ItemsControl Klasse zu bekommen und nichts scheint zu funktionieren. Alle ListBox Proben sah ich ListBoxItem als Zieltyp für den Stil verwenden, die den Hintergrund auf AlternationIndex Basis setzt - wie dieses von MSDN:Wie wird AlternationIndex in ItemsControls verwendet?

<Grid> 
    <Grid.Resources> 
     <Style x:Key="alternatingWithTriggers" TargetType="{x:Type ListBoxItem}"> 
      <Setter Property="Background" Value="Blue"/> 
      <Setter Property="Foreground" Value="White"/> 
      <Style.Triggers> 
       <Trigger Property="ListBox.AlternationIndex" Value="1"> 
        <Setter Property="Background" Value="CornflowerBlue"/> 
        <Setter Property="Foreground" Value="Black"/> 
       </Trigger> 
       <Trigger Property="ListBox.AlternationIndex" Value="2"> 
        <Setter Property="Background" Value="LightBlue"/> 
        <Setter Property="Foreground" Value="Navy"/> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 

    </Grid.Resources> 
    <ListBox AlternationCount="3" ItemsSource="{StaticResource data}" 
      ItemContainerStyle="{StaticResource alternatingWithTriggers}"> 
    </ListBox> 
</Grid> 

Ich möchte verwenden, um die ItemsControl, weil ich nicht die Auswahl Funktionalität wollen und Ich denke, ein ListBox Restyling, um es zu verstecken, könnte nicht die beste Wahl sein.

Dies ist eines der Dinge, die ich habe versucht:

<DataTemplate DataType="{x:Type vm:ObservableCollectionItem}"> 
    <Grid> 
     <!-- some content here --> 
    </Grid> 
</DataTemplate> 

<!-- ... --> 

<ItemsControl 
    ItemsSource="{Binding ObservableCollectionItems}" 
    AlternationCount="2" 
> 
    <ItemsControl.ItemContainerStyle> 
     <Style> 
      <Style.Triggers> 
       <Trigger Property="ItemsControl.AlternationIndex" Value="0"> 
        <Setter Property="Grid.Background" Value="Red"></Setter> 
       </Trigger> 
       <Trigger Property="ItemsControl.AlternationIndex" Value="1"> 
        <Setter Property="Grid.Background" Value="Blue"></Setter> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
    </ItemsControl.ItemContainerStyle> 
</ItemsControl> 

Das Problem, das ich sah, war, dass die visuelle Struktur eine Liste von ContentPresenter s hat, die ItemsControl.AlternationIndex wechseln zwischen 0 und 1, aber die Grid in jeweils ContentPresenter hat ItemsControl.AlternationIndex

Es auf 0 gesetzt ist wahrscheinlich etwas offensichtlich fehlt mir ...

Antwort

38

Die ItemContainerStyle auf die von erzeugten Elemente angelegt wird das ItemsControl: ContentPresenter. Der ContentPresenter enthält seinerseits alles, was Sie in Ihr ItemTemplate eingegeben haben. Im Falle einer ListBox wird der ItemContainerStyle auf das generierte ListBoxItem angewendet.

Der AlternationCount ist basierend auf dem, was Sie gepostet haben, nur für diese generierten Elemente verfügbar. Sie können den ItemContainerStyle nicht verwenden, um den Hintergrund des Rasters festzulegen, da das Raster für diesen Stil unbekannt ist.

Folgendes wäre ideal, aber leider hat ContentPresenter keine Hintergrundeigenschaft. Es würde jedoch für eine ListBox (mit ListBoxItems) funktionieren.

<ItemsControl 
    ItemsSource="{Binding ObservableCollectionItems}" 
    AlternationCount="2"> 
    <ItemsControl.ItemContainerStyle> 
     <Style TargetType="ContentPresenter"> 
      <Style.Triggers> 
       <Trigger Property="ItemsControl.AlternationIndex" Value="0"> 
        <Setter Property="Background" Value="Red"></Setter> 
       </Trigger> 
       <Trigger Property="ItemsControl.AlternationIndex" Value="1"> 
        <Setter Property="Background" Value="Blue"></Setter> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
    </ItemsControl.ItemContainerStyle> 
</ItemsControl> 

So beenden Sie einen Stil für das Gitter zu schreiben, die auf das Alter Ihres Muttercontent bindet.

<DataTemplate DataType="{x:Type vm:ObservableCollectionItem}"> 
    <Grid> 
     <Grid.Style> 
      <Style TargetType="Grid"> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, Path=(ItemsControl.AlternationIndex)}" Value="0"> 
         <Setter Property="Background" Value="Red"/> 
        </DataTrigger> 
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, Path=(ItemsControl.AlternationIndex)}" Value="1"> 
         <Setter Property="Background" Value="Blue"/> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </Grid.Style> 
    </Grid> 
</DataTemplate> 
+0

Es hat funktioniert! Vielen Dank! Ich frage mich, ob diese Lookup-Bindung auf großen ItemControls skalieren würde, aber zum Glück ist das nicht der Fall. –

+1

Das zweite Beispiel funktioniert, das erste nicht, da der ContentPresenter * keine * Eigenschaft 'Background' hat. – Will

+8

Wie ich direkt vor dem Beispiel sage;) – Bubblewrap

24

hm .. Nach ca. 2 Stunden herumspielen, fand ich endlich die Lösung, die einfach funktioniert:

 <ItemsControl ItemsSource="{Binding}" AlternationCount="2"> 
       <ItemsControl.ItemTemplate> 
        <DataTemplate> 
         <Grid Background="Transparent" x:Name="__PART_GRID"></Grid> 
         <DataTemplate.Triggers> 
          <Trigger Property="ItemsControl.AlternationIndex" Value="0"> 
           <Setter TargetName="__PART_GRID" Property="Background" Value="Red"/> 
          </Trigger> 
          <Trigger Property="ItemsControl.AlternationIndex" Value="1"> 
           <Setter TargetName="__PART_GRID" Property="Background" Value="Blue"/> 
          </Trigger> 
         </DataTemplate.Triggers> 
        </DataTemplate> 
       </ItemsControl.ItemTemplate> 
     </ItemsControl> 

Ich hoffe, dass diese Antwort anderen hilft, einige Zeit zu sparen.

+0

Diese Lösung ist ** viel ** klarer als eine, die von @Bubblewrap vorgeschlagen wird, also ... +1! Vielen Dank! – AxelEckenberger

+0

Definitiv eine viel sauberere Lösung, IMO. Es ist vielleicht erwähnenswert, dass die benannte Komponente vor den Auslösern kommen muss oder einen Fehler auslösen wird. (Obwohl die Fehlermeldung ziemlich klar ist, was das Problem ist) – Herohtar

0

Wenn Sie nicht die DataTemplate-Methode verwenden möchten, können Sie ein benutzerdefiniertes Steuerelement erstellen, das ContentControl als Objektcontainer verwendet. Daher können Sie eine Hintergrundfarbe angeben.

Klasse:

public class ItemsControlAlternating : ItemsControl 
{ 
    static ItemsControlAlternating() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(ItemsControlAlternating), 
       new FrameworkPropertyMetadata(typeof(ItemsControlAlternating))); 
    } 

    protected override DependencyObject GetContainerForItemOverride() 
    { 
     return new ContentControl(); 
    } 

    protected override bool IsItemItsOwnContainerOverride(object item) 
    { 
     return item is ContentControl; 
    } 
} 

Ressourcen Wörterbuch:

<Style TargetType="{x:Type c:ItemsControlAlternating}"> 
    <Setter Property="AlternationCount" Value="2"/> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type c:ItemsControlAlternating}"> 
       <ItemsPresenter/> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
    <Setter Property="ItemContainerStyle"> 
     <Setter.Value> 
      <Style TargetType="{x:Type ContentControl}"> 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate TargetType="{x:Type ContentControl}"> 
          <Border Background="{TemplateBinding Background}"> 
           <ContentPresenter/> 
          </Border> 
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 
       <Style.Triggers> 
        <Trigger Property="ItemsControl.AlternationIndex" Value="0"> 
         <Setter Property="Background" Value="Gray"/> 
        </Trigger> 
        <Trigger Property="ItemsControl.AlternationIndex" Value="1"> 
         <Setter Property="Background" Value="White"/> 
        </Trigger> 
       </Style.Triggers> 
      </Style> 
     </Setter.Value> 
    </Setter> 
</Style> 
0

Ich weiß nicht, wie jeder der früheren Antworten legit sind. Ich konnte keinen von ihnen zum Arbeiten bringen (habe Jacobi aber nicht probiert). Wie auch immer, ich fand den Pfad zur Erleuchtung hier: http://www.dotnetcurry.com/wpf/1211/wpf-items-control-advanced-topic, was mich dazu brachte, das Folgende in den XAML hinzuzufügen.cs Code-Behind:

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

und dies in dem XAML selbst

<local:CustomItemsControl AlternationCount="2" 
      ItemsSource="{Binding Cells, Mode=OneWay}"> 
     <local:CustomItemsControl.ItemContainerStyle> 
      <Style TargetType="ContentControl"> 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate TargetType="ContentControl"> 
          <Border Background="{TemplateBinding Background}"> 
           <ContentPresenter/> 
          </Border> 
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 

       <Style.Triggers> 
        <Trigger Property="ItemsControl.AlternationIndex" Value="0"> 
         <Setter Property="Background" Value="WhiteSmoke"/> 
        </Trigger> 
        <Trigger Property="ItemsControl.AlternationIndex" Value="1"> 
         <Setter Property="Background" Value="LightGray"/> 
        </Trigger> 
       </Style.Triggers> 
      </Style> 
     </local:CustomItemsControl.ItemContainerStyle> 
    </local:CustomItemsControl> 

Das war so verdammt schwer, eine funktionierende Lösung zu, dass ich wirklich wütend

1

bin zu finden oder, wie ich auf einen anderen Dienstposten gefunden, und es funktioniert gut für mich ... Sie einfach eine Bindung verwenden können ...

{Binding 
    RelativeSource={RelativeSource Mode=TemplatedParent}, 
    Path=(ItemsControl.AlternationIndex)} 

NB: Denken Sie daran, AlterationCount = "100" auf Ihrem ItemsControl hinzuzufügen

Verwandte Themen