2012-06-30 17 views
12

Provo a creare un ListView con generazione dinamica di colonne. Io uso mvvm patern. Come posso implementarlo? In questo momemt ho solo colonne statiche.Generazione dinamica colonna 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> 

risposta

41

È possibile creare GridView con colonne appropriate dinamicamente utilizzando convertitore. esempio è lavoro:

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

Pazzo, ti meriti +100 per questa risposta ... – Thomas

+0

100 se potessi troppo. Così bene ho creato un esempio di implementazione di questo (e anche l'aggiunta di ordinamento delle colonne aggiunte dinamicamente) e l'ho trasferito a GitHub all'indirizzo https://github.com/9swampy/DynamicPropertyPropertiesListGridViewExample – 9swampy

+0

Un altro teorico +100 da me. Non posso credere che ci sia voluto così tanto tempo per scoprire come farlo, ed è molto più pulito di altre implementazioni. – Grim

0

Grazie Sergei, per una risposta meravigliosa.

L'ho usato in una forma leggermente diversa, poiché avevo bisogno di aggiungere colonne con tipi di dati non di testo.

Quindi la seguente modifica alla risposta di Sergei consente di disporre di wrapper ContentControl sui valori dei dati. Saranno quindi renderizzati in base ai DataTemplates definiti per i valori in ogni cella.

La colonna sarà avvolto se ContentControlDataField viene utilizzato piuttosto che TextDataField (originariamente 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; } 
} 
Problemi correlati