2013-02-01 27 views
13

Tôi có ObservableCollection chứa các kiểu xem nhiều loại, và tôi muốn tạo một DataTemplate cho mỗi kiểu trong mỗi CellTemplates của GridViewColumn của tôi. Trong ví dụ đơn giản này, tôi có thể tạo một ViewModel cơ sở, nhưng tôi muốn có thể thực hiện điều này chỉ từ xaml. Các xaml dưới đây cho thấy những gì tôi đang cố gắng để làm, nơi mà một trong những DataTemplates sẽ được sử dụng cho mỗi CellTemplate.DataTemplate cho mỗi DataType trong GridViewColumn CellTemplate

Nếu có một GridViewColumn.Resources tôi sẽ định nghĩa DataTemplates ở đó, sau đó sử dụng một DataTemplate với ContentPresenter trong CellTemplate, nhưng tôi rõ ràng không thể làm điều đó. Tôi nghĩ rằng tôi có thể cần một TemplateSelector, nhưng tôi không chắc chắn nơi để bắt đầu.

<ListView ItemsSource={Binding GenericObservableCollection> 
    <ListView.View> 
     <GridView> 
      <GridViewColumn Header="Type"> 
       <GridViewColumn.CellTemplate> 
        <DataTemplate DataType="{x:Type vm:ActionInputViewModel}"> 
         <TextBlock Text="Input"/> 
        </DataTemplate> 
        <DataTemplate DataType="{x:Type vm:ActionOutputViewModel}"> 
         <TextBlock Text="Output"/> 
        </DataTemplate> 
       </GridViewColumn.CellTemplate> 
      </GridViewColumn> 
      <GridViewColumn Header="Value"> 
       <GridViewColumn.CellTemplate> 
        <DataTemplate DataType="{x:Type vm:ActionInputViewModel}"> 
         <TextBlock Text="{Binding Property1}"/> 
        </DataTemplate> 
        <DataTemplate DataType="{x:Type vm:ActionOutputViewModel}"> 
         <TextBlock Text="{Binding Property2}"/> 
        </DataTemplate> 
       </GridViewColumn.CellTemplate> 
      </GridViewColumn> 
     </GridView> 
    </ListView.View> 
</ListView> 

Trả lời

30

Có một vài cách khác nhau bạn có thể truy cập tại đây. Bạn có thể viết một DataTemplateSelector và gán đó đến GridViewColumn.CellTemplateSelector tài sản:

public class ViewModelTemplateSelector : DataTemplateSelector 
{ 
    public DataTemplate InputTemplate { get; set; } 
    public DataTemplate OutputTemplate { get; set; } 

    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
     return (item is ActionInputViewModel) ? InputTemplate : OutputTemplate; 
    } 
} 

Sau đó, bạn có thể di chuyển tất cả các mẫu để Resources nơi nào đó - ở đây tôi vừa bị mắc kẹt trong ListView cho ngắn gọn:

<ListView ItemsSource="{Binding GenericObservableCollection}"> 
     <ListView.Resources> 
      <DataTemplate x:Key="InLabel" DataType="{x:Type vm:ActionInputViewModel}"> 
       <TextBlock Text="Input"/> 
      </DataTemplate> 
      <DataTemplate x:Key="OutLabel" DataType="{x:Type vm:ActionOutputViewModel}"> 
       <TextBlock Text="Output"/> 
      </DataTemplate> 
      <DataTemplate x:Key="InValue" DataType="{x:Type vm:ActionInputViewModel}"> 
       <TextBlock Text="{Binding Property1}"/> 
      </DataTemplate> 
      <DataTemplate x:Key="OutValue" DataType="{x:Type vm:ActionOutputViewModel}"> 
       <TextBlock Text="{Binding Property2}"/> 
      </DataTemplate> 
     </ListView.Resources> 
     <ListView.View> 
      <GridView> 
       <GridViewColumn Header="Type"> 
        <GridViewColumn.CellTemplateSelector> 
         <vm:ViewModelTemplateSelector InputTemplate="{StaticResource InLabel}" OutputTemplate="{StaticResource OutLabel}"/> 
        </GridViewColumn.CellTemplateSelector> 
       </GridViewColumn> 
       <GridViewColumn Header="Value"> 
        <GridViewColumn.CellTemplateSelector> 
         <vm:ViewModelTemplateSelector InputTemplate="{StaticResource InValue}" OutputTemplate="{StaticResource OutValue}"/> 
        </GridViewColumn.CellTemplateSelector> 
       </GridViewColumn> 
      </GridView> 
     </ListView.View> 
    </ListView> 

Ngoài ra, nếu bạn muốn giữ tất cả trong XAML, bạn có thể dựa vào DataTypes để giải quyết các mẫu phù hợp với mình. Thông thường bạn chỉ cần đặt chúng vào bộ sưu tập Tài nguyên của vùng chứa gần nhất nhưng tiếc là GridViewColumn không phải là một phần tử giao diện người dùng nên không có một bộ sưu tập Tài nguyên. Bạn có thể giải quyết vấn đề này bằng cách thêm vào một ContentControl cho từng ô có thể giữ các mẫu được nhập riêng của mình:

<ListView ItemsSource="{Binding GenericObservableCollection}"> 
     <ListView.View> 
      <GridView> 
       <GridViewColumn Header="Type"> 
        <GridViewColumn.CellTemplate> 
         <DataTemplate> 
          <ContentControl Content="{Binding}"> 
           <ContentControl.Resources> 
            <DataTemplate DataType="{x:Type vm:ActionInputViewModel}"> 
             <TextBlock Text="Input"/> 
            </DataTemplate> 
            <DataTemplate DataType="{x:Type vm:ActionOutputViewModel}"> 
             <TextBlock Text="Output"/> 
            </DataTemplate> 
           </ContentControl.Resources> 
          </ContentControl> 
         </DataTemplate> 
        </GridViewColumn.CellTemplate> 
       </GridViewColumn> 
       <GridViewColumn Header="Value"> 
        <GridViewColumn.CellTemplate> 
         <DataTemplate> 
          <ContentControl Content="{Binding}"> 
           <ContentControl.Resources> 
            <DataTemplate DataType="{x:Type vm:ActionInputViewModel}"> 
             <TextBlock Text="{Binding Property1}"/> 
            </DataTemplate> 
            <DataTemplate DataType="{x:Type vm:ActionOutputViewModel}"> 
             <TextBlock Text="{Binding Property2}"/> 
            </DataTemplate> 
           </ContentControl.Resources> 
          </ContentControl> 
         </DataTemplate> 
        </GridViewColumn.CellTemplate> 
       </GridViewColumn> 
      </GridView> 
     </ListView.View> 
    </ListView> 

Dù bằng cách nào cũng cho bạn kết quả tương tự.

+0

Hoàn hảo. Cảm ơn bạn đã cung cấp câu trả lời chi tiết cho cả hai cách tiếp cận mà tôi đã xem xét. – scuba88

+0

Geez, tôi đã sooo gần sau khi flailing giờ, nhưng bạn đóng đinh nó. Lỗi của tôi là tôi đã ràng buộc 'DataContext' của' ContentControl', trái với 'Nội dung' như bạn đã chỉ ra một cách chính xác. Kudo và cảm ơn. –

+0

Tôi thích nó khi mọi người thực sự dành thời gian cho câu trả lời của họ. Hiển nhiên trong chi tiết bạn đã cung cấp. Công việc tốt. +1. – cplotts