2010-08-25 9 views
22

Tôi đã xem một số bài viết cho thấy cách sử dụng AlternationIndex với ListBox es hoặc ListView s, nhưng tôi đã dành một vài giờ cố gắng để có được màu nền xen kẽ trên lớp cơ sở ItemsControl và không có gì có vẻ hiệu quả. Tất cả ListBox mẫu tôi thấy sử dụng ListBoxItem như các loại mục tiêu cho phong cách mà bộ nền dựa trên AlternationIndex - như thế này từ MSDN:Làm thế nào để sử dụng AlternationIndex trong ItemsControls?

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

Tôi muốn sử dụng ItemsControl bởi vì tôi không muốn các chức năng lựa chọn và Tôi nghĩ rằng restyling một ListBox để ẩn nó có thể không phải là sự lựa chọn tốt nhất.

Đây là một trong những điều tôi đã cố gắng:

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

Vấn đề tôi thấy là cây thị giác có một danh sách các ContentPresenter s có ItemsControl.AlternationIndex luân phiên giữa 0 và 1, nhưng Grid trong mỗi ContentPresenter đã ItemsControl.AlternationIndex thiết lập để 0.

có lẽ là một cái gì đó rõ ràng tôi đang thiếu ...

Trả lời

38

các ItemContainerStyle được áp dụng cho các yếu tố được tạo ra bởi các ItemsControl: ContentPresenter. ContentPresenter sẽ lần lượt chứa bất cứ thứ gì bạn đưa vào ItemTemplate của bạn. Trong trường hợp của một ListBox, ItemContainerStyle được áp dụng cho ListBoxItem được tạo ra.

AlternationCount, dựa trên những gì bạn đã đăng, chỉ khả dụng trên các mục được tạo này. Bạn không thể sử dụng ItemContainerStyle để thiết lập nền của Grid, vì Grid không được biết đến với Style đó.

Sau đây là lý tưởng, nhưng tiếc là ContentPresenter không có thuộc tính nền. Nó sẽ làm việc cho một ListBox (với ListBoxItems) tuy nhiên.

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

Vì vậy, bạn kết thúc viết kiểu cho lưới liên kết với AlternationIndex của ParentPresenter mẹ.

<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

Đã hoạt động! Cảm ơn! Tôi tự hỏi nếu điều này tra cứu ràng buộc sẽ quy mô lớn ItemControls, nhưng may mắn thay tôi không phải là trường hợp. –

+1

Ví dụ thứ hai hoạt động, ví dụ đầu tiên không, vì ContentPresenter không * không * có thuộc tính 'Background'. – Will

+8

Giống như tôi nói ngay trước ví dụ;) – Bubblewrap

24

hm .. Sau khoảng 2 giờ chơi xung quanh, tôi cuối cùng đã tìm thấy các giải pháp mà chỉ đơn giản là hoạt động:

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

Tôi hy vọng câu trả lời này sẽ giúp những người khác để tiết kiệm thời gian.

+0

Giải pháp này là ** nhiều ** rõ ràng hơn một đề xuất bởi @Bubblewrap vì vậy ... +1! Cảm ơn! – AxelEckenberger

+0

Chắc chắn là một giải pháp sạch hơn, IMO. Nó có thể đáng chú ý, thành phần được đặt tên PHẢI đến trước các trigger hoặc nó sẽ ném một lỗi. (Mặc dù, thông báo lỗi khá rõ ràng về vấn đề là gì) – Herohtar

0

Nếu bạn không muốn sử dụng phương pháp DataTemplate, bạn có thể tạo điều khiển tùy chỉnh sử dụng ContentControl làm vùng chứa, do đó cho phép bạn chỉ định màu nền.

Class:

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

điển Resource:

<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

Tôi không biết làm thế nào một trong các câu trả lời trước được VN. Tôi không thể làm cho bất kỳ người trong số họ làm việc (không thử Jacobi mặc dù). Dù sao, tôi đã tìm thấy con đường dẫn đến chứng ngộ ở đây: http://www.dotnetcurry.com/wpf/1211/wpf-items-control-advanced-topic, điều này dẫn tôi đến việc thêm những điều sau vào xaml.cs code-behind:

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

và điều này trong XAML tự

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

này rất vất vả để tìm một giải pháp làm việc với tôi thực sự tức giận

1

Hoặc, như tôi tìm thấy trên một bài đăng khác, và nó hoạt động tuyệt vời cho tôi ... Bạn có thể chỉ cần sử dụng một ràng buộc ...

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

NB: hãy nhớ thêm AlterationCount = "100" vào ItemsControl của bạn