2012-06-30 89 views
12

我嘗試使列動態生成一個ListView。我使用mvvm patern。 我怎麼能實現這個? 在這個momemt我只有靜態列。動態生成列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> 

回答

41

您可以使用轉換器動態地創建GridView和相應的列。這裏是工作示例:

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

瘋狂,你值得擁有+100這個答案... – Thomas

+0

+100如果我也能。好,我已經做了一個實現這個(並添加動態添加列的排序)的示例,並將其推送到GitHub上https://github.com/9swampy/DynamicPropertyPropertiesListGridViewExample – 9swampy

+0

另一個理論+100從我。我不敢相信這花了我很長時間才找到如何做到這一點,並且比其他實現更清潔。 – Grim

0

謝謝謝爾蓋,一個奇妙的答案。

我使用它的形式稍有不同,因爲我需要添加具有非文本數據類型的列。

因此,對Sergei答案的以下修改允許您在數據值上擁有ContentControl封裝器。然後根據爲每個單元格中的值定義的數據模板渲染它們。如果ContentControlDataField而不是使用TextDataField(原數據字段)

列將被包裝:

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