DataGridColumn在代码中绑定

Ber*_*ryl 1 data-binding silverlight wpf datagrid

有谁知道我怎么能在代码中进行等效的XAML绑定?

<DataGrid ... >
    <DataGrid.Columns>
        <DataGridTextColumn 
            Binding="{Binding Description}"  <=== set in code **
        />
    </DataGrid.Columns>
</DataGrid>
Run Code Online (Sandbox Code Playgroud)

干杯,
Berryl

===更新====

看起来我一直在寻找的方法是DataGridColumn.GenerateElement

如果是这样,那么这个问题的焦点现在是如何正确设置Binding.我想要做这个代码的原因是我的网格有7列在视觉上相同,其数据可以通过索引知道.

所以我希望能够通过使用具有索引属性的子类DataGridTextColumn来简化xaml,并且只需:

<DataGrid ... >
    <DataGrid.Columns >
        <local:DayOfWeekColumn Index="0" />
        <local:DayOfWeekColumn Index="1" />
        ....
        <local:DayOfWeekColumn Index="7" />
    </DataGrid.Columns >
</DataGrid >
Run Code Online (Sandbox Code Playgroud)

===修改过的问题===

假设Binding本身在逻辑上和语法上都是正确的,那么BindingOperations.SetBinding的参数应该是什么?

    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem) {
        var activity = (ActivityViewModel)dataItem;
        var cellData = activity.Allocations[Index];
        var b = new Binding
                {
                    Source = cellData,
                    UpdateSourceTrigger = UpdateSourceTrigger.LostFocus,
                    Converter = new AllocationAmountConverter()
                };


        BindingOperations.SetBinding(??, ??, b);
        return ??;
    }
Run Code Online (Sandbox Code Playgroud)

=== ARAN的编辑=====

我现在没有覆盖GenerateElement,而是试图获取一个静态帮助器来为我设置绑定.在任何情况下都需要帮助程序来补偿无法在MSFT的DataGrid的当前实现中绑定Header内容.

基本上,这个想法是从网格中捕获DC并在每个列上根据需要使用它,在这种情况下,它将是Header内容,单元格样式和Binding.这是代码:

public class TimesheetDataGridColumnContextHelper
{

    static TimesheetDataGridColumnContextHelper() {
        FrameworkElement.DataContextProperty.AddOwner(typeof (DataGridTextColumn));
        FrameworkElement.DataContextProperty.OverrideMetadata(
            typeof (DataGrid), 
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits, OnDataContextChanged));
    }

    public static void OnDataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var grid = d as DataGrid;
        if (grid == null || !grid.Name.Equals("adminActivityGrid")) return;

        foreach (var col in grid.Columns) {

            var dowCol = col as DayOfTheWeekColumn;
            if (dowCol == null) continue;

            var context = (IActivityCollectionViewModelBase) e.NewValue;
            var index = Convert.ToInt32(dowCol.DowIndex);

            _setHeader(dowCol, context, index);

            var editStyle = (Style) grid.FindResource("GridCellDataEntryStyle");
            dowCol.CellStyle = editStyle;

            _setBinding(dowCol, index, context);

        }
    }

    private static void _setBinding(DayOfTheWeekColumn dowCol, int index, IActivityCollectionViewModelBase context) {
        dowCol.Binding = new Binding
                         {
                             Path = new PropertyPath(string.Format("Allocations[{0}]", index)),
                             UpdateSourceTrigger = UpdateSourceTrigger.LostFocus,
                             Converter = new AllocationAmountConverter()
                         };
    }

    private static void _setHeader(DataGridColumn col, IActivityCollectionViewModelBase context, int index)
    {
        var date = context.HeaderDates[index];
        var tb = new TextBlock
                 {
                     Text = date.ToString(Strings.ShortDayOfWeekFormat),
                     ToolTip = date.ToLongDateString()
                 };
        col.Header = tb;
    }

}
Run Code Online (Sandbox Code Playgroud)

}

一切都有效,除了 Binding.我不知道是不是因为我的绑定在某种程度上是错误的(虽然我没有明显的错误)或者这不是一个设置它的好地方.运行它时,网格列只是空的.

任何的想法??

干杯,
Berryl

===固定!===

上次更新中的逻辑实际上是正确的,但是在DataGrid的内部丢失了我错过了我的Binding.Path缺少要绑定的属性!感谢Aran理解这个问题,意识到GenerateElement覆盖不是必需的,并且认识到不应该设置Binding Source.

Ara*_*and 5

你总是在做那些令人讨厌的网格...... Beryl?

做几件事.使用reflect来查看DataGridTextColumn中GenerateElement的实现.(.NET程序员住在反射器中)

现在回答:

在datagrid中,每列不是可视树的一部分.该列有两个方法GenerateElement和GenerateEditingElement.这些方法分别返回单元格的查看器和编辑器.在上面的方法中,您不是在创建查看器,它可能是一个TextBlock.

从反射器,GenerateElement的实现如下,注意他们做的第一件事就是为单元创建查看器.

protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
{
    TextBlock e = new TextBlock();
    this.SyncProperties(e);
    base.ApplyStyle(false, false, e);
    base.ApplyBinding(e, TextBlock.TextProperty);
    return e;
}
Run Code Online (Sandbox Code Playgroud)

一旦有了文本块,就可以使用下面的行来设置文本块.

BindingOperations.SetBinding(textBlock, TextBlock.TextProperty, binding);
Run Code Online (Sandbox Code Playgroud)

但我并不确信您确实需要覆盖GenerateElement和GenerateEditingElement以获得所需的效果.我认为你可以覆盖基类的Binding属性,只要在设置时用你的额外字段修改那里的绑定.这将意味着其他一切都将正常工作,您不会最终删除列中的功能.再次通过反射器查看类DataGridBoundColumn(抽象基类)将是有益的.

每当设置绑定时,我会在我们的一个列中执行类似的操作我通过添加额外的属性来修改剪贴板绑定,以便我可以有效地复制和粘贴.

编辑:更新......这应该是另一个问题,但..

您在setBinding方法中明确设置绑定源.在网格中,绑定的源是行中包含的数据.您正在设置它,这意味着每行都是相同的.在设置数据上下文之前,您可以在没有source属性的情况下应用这些时髦的绑定,源成为每行中的项,并且绑定应该反映每行中保存的属性的索引.