动态生成列 mvvm
Posted
技术标签:
【中文标题】动态生成列 mvvm【英文标题】:Dynamic generate column mvvm 【发布时间】:2012-07-01 17:58:56 【问题描述】:我尝试制作一个动态生成列的 ListView。我使用 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" />
</GridView>
</ListView.View>
</ListView>
【问题讨论】:
【参考方案1】:您可以使用转换器动态创建带有适当列的GridView
。这是工作示例:
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 gridView = new GridView();
foreach (var column in config.Columns)
var binding = new Binding(column.DataField);
gridView.Columns.Add(new GridViewColumn Header = column.Header, DisplayMemberBinding = binding);
return gridView;
return Binding.DoNothing;
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
throw new NotSupportedException();
【讨论】:
如果我也可以的话,+100。太好了,我编写了一个示例来实现这一点(并且还添加了对动态添加的列的排序)并将其推送到 GitHub github.com/9swampy/DynamicPropertyPropertiesListGridViewExample 我的另一个理论+100。我不敢相信我花了这么长时间才找到如何做到这一点,而且它比其他实现要干净得多。 我知道这已经有好几年了,但是如何使用这种方法将上下文菜单添加到视图或每列的上下文菜单?【参考方案2】:感谢 Sergei,提供了一个了不起的答案。
我以稍微不同的形式使用它,因为我需要添加非文本数据类型的列。
因此,对 Sergei 答案的以下修改允许您在数据值上使用 ContentControl 包装器。然后将根据为每个单元格中的值定义的 DataTemplates 呈现它们。
如果使用 ContentControlDataField 而不是 TextDataField(最初是 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;
【讨论】:
您的代码似乎是我需要的,因为我需要一个复选框列,但我真的不明白要在 Column.ContentControlDataField 中放入什么才能完成我需要的操作,您能帮帮我吗? 感谢您的代码 - 我尝试使用它。您是否知道为什么在运行时更改 ColumnConfig 不会刷新视图?我将 Columns 更改为 ObservableCollection [编辑:认为它现在可以工作,我的 ViewModel 上缺少一些 OnPropertyChanges]以上是关于动态生成列 mvvm的主要内容,如果未能解决你的问题,请参考以下文章