2010-08-08 115 views
1

有誰知道我可以如何在代碼中執行等效的XAML綁定?代碼中的DataGridColumn綁定

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

乾杯,
Berryl

=== UPDATE ====

它看起來像我一直在尋找的方法是DataGridColumn.GenerateElement

如果是這樣,那麼這個問題的焦點是如何正確設置Binding。我想做這個代碼的原因是我的網格有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 ??; 
    } 

=== EDITS爲ARAN =====

我不重寫GenerateElement現在,而是試圖讓一個靜態輔助設置我爲我結合。在任何情況下都需要幫助程序來補償無法綁定當前MSFT DataGrid實現中的標題內容。

基本上這個想法是從網格中捕獲DC,並根據需要在每個列上使用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; 
    } 

} 

}

一切正常,除了綁定。我不知道是不是因爲我的綁定是錯誤的(儘管我沒有明顯的錯誤),或者這不是一個設置它的好地方。當我運行它時,網格列只是空的。

任何想法??

乾杯,
Berryl

===修復! ===

上次更新中的邏輯實際上是正確的,但在DataGrid的內部丟失了我錯過了我的Binding.Path缺少要綁定的屬性!感謝Aran瞭解這個問題,意識到GenerateElement覆蓋不是必需的,並且捕捉到綁定源不應該被設置。

回答

4

你總是在做錯誤的網格位呃Beryl?

做幾件事。使用reflector來查看DataGridTextColumn中的GenerateElement的實現。 (.NET程序員生活在反射器)

現在的答案:

DataGrid中的每一列不是視覺樹的一部分。該列有兩個方法GenerateElement和GenerateEditingElement。這些方法分別返回單元格的查看器和編輯器。在上面的方法中,您不創建查看器,該查看器可能是TextBlock。

from 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); 

我不確定您是否確實需要重寫GenerateElement和GenerateEditingElement以獲得所需的效果。我認爲你可以覆蓋基類的Binding屬性,並且只要在設置時修改與其他字段的綁定。這意味着其他所有內容都可以正常工作,而且不會從列中移除功能。再次查看類DataGridBoundColumn(抽象基類)的反射器將是有益的。

只要設置了綁定,我就可以在我們的某個列中做類似的事情我通過添加一個額外的屬性來修改剪貼板綁定,這樣我就可以有效地進行復制和粘貼。

編輯:更新...這也許應該是另一個問題,但..

你被明確設定在setBinding方法綁定的源。在網格中,綁定的來源是包含在該行中的數據。你正在設置它,這意味着每行都是一樣的。您可以在設置數據上下文之前應用這些沒有源屬性的時髦綁定,源將成爲每行中的項目,並且綁定應該反映每行中保存的屬性的索引。

+0

嗨阿蘭。是的,我的小提琴正在爲此做一個鍛鍊,但似乎值得一試。請參閱我上次的編輯(「編輯ARAN」)以獲取最新方法。乾杯! – Berryl 2010-08-09 21:35:31

+0

明白了。是我的綁定路徑中的一個蹩腳的語法錯誤(應該是「Allocations [{0}]。Amount」)感謝您的幫助! – Berryl 2010-08-11 00:18:40

0

基於MSDN,它聽起來像的SetBinding()第一參數應該是要顯示在所述結合對照(this在這種情況下,假設GenerateElement()DayOfWeekColumn類的一個成員),並且所述第二屬性是將數據綁定到的屬性。我還沒有使用WPF DataGrid,但我沒有看到任何文本屬性設置。

雖然我確實看到DataGridTextColumn確實有Binding屬性。也許它會將其設置爲您在上面手動創建的綁定?

+0

偉大的想法,我的初衷是做到這一點,但它在某種程度上使方法進入一個無限循環。什麼是PITA - 感謝您的回覆! – Berryl 2010-08-09 00:13:07