与ObservableCollection绑定的WPF DataGrid

时间:2014-11-28 08:50:22

标签: wpf xaml mvvm datagrid observablecollection

我正在尝试将带有数据行的ObservableCollection绑定到我的datagrid。 我的目标是自己进行datagrid更新(如果添加数据),使用DataTable时它不起作用。 我测试了这种方法,它运行得很好,我的datagrid绑定到ResultTable属性,属性名称是列名。

public class MainWindowViewModel
{
    public MainWindowViewModel()
    {
        ResultTable = new ObservableCollection<Row>();
        ResultTable.Add(new Row() { Name = "Peter", Age = "21", Sex = "Male" });
        ResultTable.Add(new Row() { Name = "Sara", Age = "25", Sex = "Female" });
        ResultTable.Add(new Row() { Name = "Mike", Age = "28", Sex = "Male" });
    }

    public ObservableCollection<Row> ResultTable { get; set; }
}

public class Row
{
    public string Name { get; set; }
    public string Age { get; set; }
    public string Sex { get; set; }
}

现在我的问题是,我该如何动态地做到这一点? 这是我的第二种方法,在DataGrid中看起来没什么......

public class MainWindowViewModel
{
    public MainWindowViewModel()
    {
        ResultTable = new ObservableCollection<Row>();
        var row = new Row();
        row.Columns.Add(new Item() { Name = "Name", Value = "Peter" });
        row.Columns.Add(new Item() { Name = "Age", Value = "21" });
        row.Columns.Add(new Item() { Name = "Sex", Value = "Male" });
        ResultTable.Add(row);
    }

    public ObservableCollection<Row> ResultTable { get; set; }
}

public class Row
{
    public List<Item> Columns = new List<Item>();
}

public class Item
{
    public string Name { get; set; }
    public string Value { get; set; }
}

但现在的问题是,我怎么能说DataGrid列List中的每个Name属性都是列标题。 每个值都是行的值?

这是我的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:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:MainWindowViewModel x:Name="MainWindowViewModel" />
    </Window.DataContext>
    <Grid>
        <DataGrid ItemsSource="{Binding ResultTable}"
                  AutoGenerateColumns="True" />
    </Grid>
</Window>

1 个答案:

答案 0 :(得分:1)

好的,所以测试了这个并按照下面的评论中的图表工作。

行类

public class Row
{
    private ObservableCollection<Item> columns = new ObservableCollection<Item>();

    public Row(params Item[] items)
    {
        foreach (var item in items)
            Columns.Add(item);
    }

    public ObservableCollection<Item> Columns
    {
        get { return columns; }
        set { columns = value; }
    }
}

Item.cs

public class Item 
{
    public Item(string name, string value)
    {
        this.Name = name;
        this.Value = value;
    }
    public string Name { get; set; }
    public string Value { get; set; }     
}

自定义DataGRidBoundColumn

public class CustomBoundColumn : DataGridBoundColumn
{
    public string TemplateName { get; set; }

    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        var binding = new Binding(((Binding)Binding).Path.Path);
        binding.Source = dataItem;

        var content = new ContentControl();
        content.ContentTemplate = (DataTemplate)cell.FindResource(TemplateName);
        content.SetBinding(ContentControl.ContentProperty, binding);
        return content;
    }

    protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
    {
        return GenerateElement(cell, dataItem);
    }
}

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public ObservableCollection<Row> ResultTable
    {
        get;
        set;
    }
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
        Loaded += (s, args) =>
            {
                this.ResultTable = new ObservableCollection<Row>();
                ResultTable.Add(new Row(new Item("Name", "Peter"), new Item("Age", "21"), new Item("Sex", "Male")));
                ResultTable.Add(new Row(new Item("Name", "Sara"), new Item("Age", "25"), new Item("Sex", "Female")));
                ResultTable.Add(new Row(new Item("Name", "Mike"), new Item("Age", "28"), new Item("Sex", "Male")));

                var columns = ResultTable.First()
                           .Columns
                           .Select((x, i) => new { Name = x.Name, Value = x.Value, Index = i })
                           .ToArray();

                foreach (var column in columns)
                {
                    var binding = new Binding(string.Format("Columns[{0}].Value", column.Index));
                    data.Columns.Add(new CustomBoundColumn()
                        {
                            Header = column.Name,
                            Binding = binding,
                            TemplateName = "CustomTemplate"
                        });                        
                }
                data.ItemsSource = this.ResultTable;

            };
    }
}

最后xaml很简单

 <Window.Resources>
    <DataTemplate x:Key="CustomTemplate">
        <Border Padding="3">
            <TextBlock Text="{Binding}" Foreground="Black" />
        </Border>
    </DataTemplate>
</Window.Resources>

    <Grid>
        <DataGrid Name="data"
                  AutoGenerateColumns="False">            
        </DataGrid>
    </Grid>     

这是在后面的代码中完成的,但我想你可以调整你的viewmodel。 有关此修复程序的更多信息,请参见Here