2012-06-30 20 views
12

Tôi cố gắng tạo một ListView với tạo cột động. Tôi sử dụng mvvm patern. Làm thế nào tôi có thể thực hiện điều này? Trong momemt này, tôi chỉ có các cột tĩnh.Cột tạo động mvvm

<ListView ItemsSource="{Binding ProblemProducts}" 
        Grid.Row="1" Grid.RowSpan="4" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Column="4"> 
      <ListView.View> 
       <GridView> 
        <GridViewColumn Header="Spisujący" DisplayMemberBinding="{Binding _spisujacy}" Width="auto"/> 
        <GridViewColumn Header="Miejsce składowania" DisplayMemberBinding="{Binding MiejsceSkladowania}" Width="auto"/> 
        <GridViewColumn Header="Typ spisu" DisplayMemberBinding="{Binding _typSpisu}" Width="auto"/> 
        <GridViewColumn Header="Kod" DisplayMemberBinding="{Binding Kod}" width="auto"/> 
       </GridView> 
      </ListView.View> 
     </ListView> 

Trả lời

41

Bạn có thể tạo GridView với các cột thích hợp sử dụng công cụ chuyển đổi. ví dụ ở đây đang làm việc:

App screen shot

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:WpfApplication1="clr-namespace:WpfApplication1" 
     mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     d:DesignHeight="189" d:DesignWidth="312" Width="300" Height="300"> 
    <Window.Resources> 
     <WpfApplication1:ConfigToDynamicGridViewConverter x:Key="ConfigToDynamicGridViewConverter" /> 
    </Window.Resources> 
    <ListView ItemsSource="{Binding Products}" View="{Binding ColumnConfig, Converter={StaticResource ConfigToDynamicGridViewConverter}}"/>  
</Window> 

MainWindow.xaml.cs

using System.Collections.Generic; 
using System.Windows; 

namespace WpfApplication1 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      DataContext = new ViewModel(); 
     } 
    } 

    public class ViewModel 
    { 
     public ColumnConfig ColumnConfig { get; set; } 
     public IEnumerable<Product> Products { get; set; } 

     public ViewModel() 
     { 
      Products = new List<Product> { new Product { Name = "Some product", Attributes = "Very cool product" }, new Product { Name = "Other product", Attributes = "Not so cool one" } }; 
      ColumnConfig = new ColumnConfig { Columns = new List<Column> { new Column { Header = "Name", DataField = "Name" }, new Column { Header = "Attributes", DataField = "Attributes" } } }; 
     } 
    } 

    public class ColumnConfig 
    { 
     public IEnumerable<Column> Columns { get; set; } 
    } 

    public class Column 
    { 
     public string Header { get; set; } 
     public string DataField { get; set; } 
    } 

    public class Product 
    { 
     public string Name { get; set; } 
     public string Attributes { get; set; } 
    } 
} 

ConfigToDynamicGridViewConverter.cs

using System; 
using System.Globalization; 
using System.Windows.Controls; 
using System.Windows.Data; 

namespace WpfApplication1 
{ 
    public class ConfigToDynamicGridViewConverter : IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      var config = value as ColumnConfig; 
      if (config != null) 
      { 
       var grdiView = new GridView(); 
       foreach (var column in config.Columns) 
       { 
        var binding = new Binding(column.DataField); 
        grdiView.Columns.Add(new GridViewColumn {Header = column.Header, DisplayMemberBinding = binding}); 
       } 
       return grdiView; 
      } 
      return Binding.DoNothing; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      throw new NotSupportedException(); 
     } 
    } 
} 
+4

Crazy, bạn xứng đáng +100 cho câu trả lời này ... – Thomas

+0

+100 nếu tôi có thể quá. Vì vậy, tốt tôi đã thực hiện một ví dụ thực hiện điều này (và cũng có thể thêm phân loại các cột động được thêm vào) và đẩy nó vào GitHub tại https://github.com/9swampy/DynamicPropertyPropertiesListGridViewExample – 9swampy

+0

Một lý thuyết khác 100 từ tôi. Tôi không thể tin rằng nó đã cho tôi quá lâu để tìm cách để làm điều này, và nó sạch hơn rất nhiều so với các triển khai khác. – Grim

0

Cảm ơn Sergei, vì một câu trả lời tuyệt vời.

Tôi đã sử dụng nó ở dạng hơi khác, vì tôi cần thêm cột có kiểu dữ liệu không phải văn bản.

Vì vậy, sửa đổi sau đây để trả lời của Sergei cho phép bạn có trình bao bọc ContentControl trên các giá trị dữ liệu. Sau đó, chúng sẽ được hiển thị theo DataTemplates được định nghĩa cho các giá trị trong mỗi ô.

Cột này sẽ được bao bọc nếu ContentControlDataField được sử dụng chứ không phải là TextDataField (ban đầu DataField):

public class ConfigToDynamicGridViewConverter : IValueConverter { 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { 
     var config = value as ColumnConfig; 
     if (config != null) { 
      var grdiView = new GridView(); 
      foreach (var column in config.Columns) { 
       bool cc = !string.IsNullOrEmpty(column.ContentControlDataField); 
       var binding = new Binding(cc ? column.ContentControlDataField : column.TextDataField); 
       if (cc) { 
        var template = new DataTemplate(); 
        var fact = new FrameworkElementFactory(typeof(ContentControl)); 
        fact.SetBinding(ContentControl.ContentProperty, binding); 
        template.VisualTree = fact; 
        grdiView.Columns.Add(new GridViewColumn {Header = column.Header, CellTemplate = template}); 
       } else 
        grdiView.Columns.Add(new GridViewColumn {Header = column.Header, DisplayMemberBinding = binding}); 
      } 
      return grdiView; 
     } 
     return Binding.DoNothing; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { 
     throw new NotSupportedException(); 
    } 
} 

public class ColumnConfig { 
    public IEnumerable<Column> Columns { get; set; } 
} 

public class Column { 
    public string Header { get; set; } 
    public string TextDataField { get; set; } 
    public string ContentControlDataField { get; set; } 
}