代码之家  ›  专栏  ›  技术社区  ›  Berryl

代码中的DataGridColumn绑定

  •  1
  • Berryl  · 技术社区  · 16 年前

    有人知道我如何在代码中进行等价的XAML绑定吗?

    <DataGrid ... >
        <DataGrid.Columns>
            <DataGridTextColumn 
                Binding="{Binding Description}"  <=== set in code **
            />
        </DataGrid.Columns>
    </DataGrid>
    

    干杯,
    贝里尔

    ===更新====

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

    如果是这样,那么这个问题的焦点就是如何正确地设置绑定。我之所以要这样做是因为我的网格有7列,它们在视觉上是相同的,并且它们的数据可以通过索引来识别。

    因此,我希望能够通过使用子类DataGridTextColumn来简化XAML,该子类具有索引属性,并且只具有:

    <DataGrid ... >
        <DataGrid.Columns >
            <local:DayOfWeekColumn Index="0" />
            <local:DayOfWeekColumn Index="1" />
            ....
            <local:DayOfWeekColumn Index="7" />
        </DataGrid.Columns >
    </DataGrid >
    

    ==修订问题===

    假设绑定本身在逻辑和语法上是正确的,那么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 ??;
        }
    

    ==编辑aran===

    我现在并不是重写generateelement,而是试图让一个静态助手为我设置绑定。在任何情况下,都需要帮助器来补偿无法在MSFT的DataGrid的当前实现中绑定头内容。

    基本上,我们的想法是从网格中捕获DC,并根据需要在每个列上使用它,在本例中,这将是头内容、单元格样式和绑定。代码如下:

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

    }

    一切正常 除了 装订。我不知道是因为我的绑定出了问题(尽管我没有明显的错误),还是因为这不是设置它的好地方。当我运行网格列时,它只是空的。

    有什么想法吗??

    干杯,
    贝里尔

    = =固定!= =

    上一次更新中的逻辑实际上是正确的,但在数据报的内部丢失了我的绑定。路径缺少要绑定的属性!感谢Aran理解这个问题,认识到GenerateElement重写是不必要的,并注意到不应该设置绑定源。

    2 回复  |  直到 16 年前
        1
  •  5
  •   Aran Mulholland JohnnyAce    16 年前

    你总是在做那些精细的网格比特,是吧,贝丽尔?

    做一些事情。使用 reflector 查看DataGridTextColumn中GenerateElement的实现。(.NET程序员生活在Reflector中)

    现在请回答:

    在DataGrid中,每一列都不是可视树的一部分。该列有两种方法GenerateElement和GenerateEditingElement。这些方法分别返回单元格的查看器和编辑器。在上面的方法中,您没有创建查看器,它可能是一个文本块。

    在Reflector中,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;
    }
    

    一旦有了一个文本块,就可以使用下面的行来设置它的绑定。

    BindingOperations.SetBinding(textBlock, TextBlock.TextProperty, binding);
    

    然而,我并不认为你真的需要超越生成和生成条件来获得你想要的效果。我想你可以把 Binding 属性,并且只要设置了额外的字段,就可以在那里修改绑定。这将意味着其他一切都将正常工作,并且您不会最终从您的专栏中删除功能。再次,通过反射器爬行查看类DataGridBoundColumn(抽象基类)将是有益的。

    我在其中一列中做了类似的事情,每当设置绑定时,我都会通过添加一个额外的属性来修改剪贴板绑定,以便有效地复制和粘贴。

    编辑:更新…这可能是另一个问题,但是……

    您正在setbinding方法中显式设置绑定的源。在网格中,绑定的源是行中包含的数据。您正在设置它,这意味着每行的值都相同。在设置数据上下文之前,可以在不使用source属性的情况下应用这些时髦的绑定,source将成为每行中的项,并且绑定应将索引反映到每行中持有的属性中。

        2
  •  0
  •   Andy    16 年前

    基于 MSDN ,听起来像是 SetBinding() 应该是要在其中显示绑定的控件( this 在这种情况下,假设 GenerateElement() 是的成员 DayOfWeekColumn 类),第二个属性是要将数据绑定到的属性。我没有用过水渍险 DataGrid 非常多,但我没有看到类似于要设置的文本属性的内容。

    我确实看到了 DataGridTextColumn 确实有 Binding 尽管如此。也许可以将其设置为上面手动创建的绑定?

    推荐文章