2012-06-30 11 views
12

Ich versuche, eine ListView mit dynamischen Generierung von Spalte zu machen. Ich benutze mvvm patern. Wie kann ich das umsetzen? In diesem Moment habe ich nur statische Spalten.Dynamic Spalte generieren 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> 

Antwort

41

Sie können GridView mit entsprechenden Spalten dynamisch mit Konverter erstellen. Hier arbeitet Beispiel:

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

Verrückt, Sie 100 für diese Antwort verdienen ... – Thomas

+0

100, wenn ich zu konnte. So gut, ich habe ein Beispiel für die Umsetzung dieser (und auch das Hinzufügen von Sortierung der dynamisch hinzugefügten Spalten) gemacht und schob es auf GitHub unter https://github.com/9swampy/DynamicPropertyPropertiesListGridViewExample – 9swampy

+0

Eine weitere theoretische +100 von mir. Ich kann nicht glauben, dass es so lange gedauert hat, das zu finden, und es ist so viel sauberer als andere Implementierungen. – Grim

0

Danke Sergei, für eine wunderbare Antwort.

Ich benutzte es in einer etwas anderen Form, da ich brauchte Spalten mit Nicht-Text-Datentypen hinzuzufügen.

Die folgende Änderung an Sergei's Antwort ermöglicht Ihnen, ContentControl-Wrapper für die Datenwerte zu verwenden. Sie werden dann gemäß den DataTemplates gerendert, die für die Werte in jeder Zelle definiert sind.

Die Spalte wird, wenn ContentControlDataField statt TextDataField verwendet wird gewickelt werden (ursprünglich 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; } 
}