结合WPF的DataGrid到数据表使用TemplateColumns [英] Binding WPF DataGrid to DataTable using TemplateColumns

查看:295
本文介绍了结合WPF的DataGrid到数据表使用TemplateColumns的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经试过一切,毫无进展,所以我希望有人可以给我惊喜的时刻。
我根本无法绑定拉成功DataGrid中的数据。

I have tried everything and got nowhere so I'm hoping someone can give me the aha moment. I simply cannot get the binding to pull the data in the datagrid successfully.

我有一个包含多个列与MyDataType的一个DataTable

I have a DataTable that contains multiple columns with of MyDataType

public class MyData
{
    string nameData {get;set;}
    bool showData {get;set;}
}

MyDataType有2个属性(字符串,一个布尔)
我创建了一个测试数据表

MyDataType has 2 properties (A string, a boolean) I have created a test DataTable

DataTable GetDummyData()
{
    DataTable dt = new DataTable("Foo");
    dt.Columns.Add(new DataColumn("AnotherColumn", typeof(MyData)));
    dt.Rows.Add(new MyData("Row1C1", true));
    dt.Rows.Add(new MyData("Row2C1", false));
    dt.AcceptChanges();
    return dt;
}

我有一个WPF的DataGrid,我想表明我的DataTable。
但是,所有我想要做的是改变每个单元的呈现方式,以显示[TextBlock中] [按钮]每个细胞与绑定到MyData的对象的值,这就是我有麻烦吨。

I have a WPF DataGrid which I want to show my DataTable. But all I want to do is to change how each cell is rendered to show [TextBlock][Button] per cell with values bound to the MyData object and this is where I'm having a tonne of trouble.

我的XAML看起来像这样

My XAML looks like this

<Window.Resources>
    <ResourceDictionary>
        <DataTemplate x:Key="MyDataTemplate" DataType="MyData">
            <StackPanel Orientation="Horizontal" >
                <Button Background="Green" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,0,0" Content="{Binding Path=nameData}"></Button>
                <TextBlock Background="Green" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5,0,0,0" Text="{Binding Path=nameData}"></TextBlock>
            </StackPanel>
        </DataTemplate>
    </ResourceDictionary>
</Window.Resources>
<Grid>
    <dg:DataGrid Grid.Row="1" ItemsSource="{Binding}" AutoGenerateColumns="True"
                 x:Name="dataGrid1" SelectionMode="Single" CanUserAddRows="False"
                 CanUserSortColumns="true" CanUserDeleteRows="False" AlternatingRowBackground="AliceBlue"
                 AutoGeneratingColumn="dataGrid1_AutoGeneratingColumn" />
</Grid>

现在我做的加载一次是尝试到DataTable的WPF的DataGrid

Now all I do once loaded is to attempt to bind the DataTable to the WPF DataGrid

dt = GetDummyData();
dataGrid1.ItemsSource = dt.DefaultView;

的TextBlock和Button显示出来,但他们没有约束力,这让他们的空白。
任何人都可以让我知道如果他们有任何想法如何解决这个问题。
这应该是简单的,那就是微软让我们相信。
我已经设置了 Col​​umn.CellTemplate AutoGenerating 事件,仍然没有得到约束力。

The TextBlock and Button show up, but they don't bind, which leaves them blank. Could anyone let me know if they have any idea how to fix this. This should be simple, thats what Microsoft leads us to believe. I have set the Column.CellTemplate during the AutoGenerating event and still get no binding.

请帮助!

推荐答案

编辑:更新,以反映阿兰穆赫兰(见注解)的输入

显然,的DataGrid 正在通过整个 DataRowView的到每个单元格。这就是为什么绑定不起作用。你的的DataTemplate 期望的DataContext 为类型迈德特,而是它的类型是 DataRowView的的。我的建议(有点劈十岁上下)的解决方法,以获得您想要的DataContext 是创建一个自定义的 DataGridTemplateColumn ,将提取从 DataRowView的必要项目。在code是如下:

Apparently the DataGrid is passing the entire DataRowView to each cell. That's why the binding doesn't work. Your DataTemplate expects the DataContext to be of type MyData, but instead it is of type DataRowView. My proposed (somewhat hack-ish) workaround to get the DataContext you want is to create a custom DataGridTemplateColumn that will extract the necessary item from the DataRowView. The code is below:

<Window x:Class="DataGridTemplateColumnSample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:dg="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <ResourceDictionary>
            <DataTemplate x:Key="MyDataTemplate" DataType="DataRowView">
                <StackPanel Orientation="Horizontal">
                    <Button Background="Green" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,0,0" Content="{Binding Path=nameData}"></Button>
                    <TextBlock Background="Green" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5,0,0,0" Text="{Binding Path=nameData}"></TextBlock>
                </StackPanel>
            </DataTemplate>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <dg:DataGrid Grid.Row="1" AutoGenerateColumns="True" x:Name="dataGrid1" SelectionMode="Single" 
                     CanUserAddRows="False" CanUserSortColumns="true" CanUserDeleteRows="False" 
                     AlternatingRowBackground="AliceBlue"  AutoGeneratingColumn="dataGrid1_AutoGeneratingColumn"
                     ItemsSource="{Binding}" VirtualizingStackPanel.VirtualizationMode="Standard" />
    </Grid>
</Window>


using System.Data;
using System.Windows;
using Microsoft.Windows.Controls;

namespace DataGridTemplateColumnSample
{
    public partial class Window1
    {
        public Window1()
        {
            InitializeComponent();
            DataContext = GetDummyData().DefaultView;
        }

        private static DataTable GetDummyData()
        {
            var dt = new DataTable("Foo");
            dt.Columns.Add(new DataColumn("OneColumn", typeof(MyData)));
            dt.Columns.Add(new DataColumn("AnotherColumn", typeof(MyData)));
            dt.Rows.Add(new MyData("Row1C1", true), new MyData("Row1C2", true));
            dt.Rows.Add(new MyData("Row2C1", false), new MyData("Row2C2", true));
            dt.AcceptChanges();
            return dt;
        }

        private void dataGrid1_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {
            var column = new DataRowColumn(e.PropertyName);
            column.Header = e.Column.Header;
            column.CellTemplate = (DataTemplate)Resources["MyDataTemplate"];
            e.Column = column;
        }
    }

    public class DataRowColumn : DataGridTemplateColumn
    {
        public DataRowColumn(string column) { ColumnName = column; }
        public string ColumnName { get; private set; }
        protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
        {
            var row = (DataRowView) dataItem;
            var item = row[ColumnName];
            cell.DataContext = item;
            var element = base.GenerateElement(cell, item);
            return element;
        }
    }

    public class MyData
    {
        public MyData(string name, bool data) { nameData = name; showData = data; }
        public string nameData { get; set; }
        public bool showData { get; set; }
    }
}

注意:此方法仅出现与容器的虚拟化关闭或在标准模式下工作。如果<一个href=\"http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingstackpanel.virtualizationmode%28v=VS.100%29.aspx\">VirtualizationMode被设置为回收不应用模板。

Note: This approach only appears to work with container virtualization off or in Standard mode. If the VirtualizationMode is set to Recycling the template is not applied.

这篇关于结合WPF的DataGrid到数据表使用TemplateColumns的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆