WPF - How to bind a DataGridTemplateColumn

2020-05-26 07:01发布

I am trying to get the name of the property associated with a particular DataGridColumn, so that I can then do some stuff based on that. This function is called when the user clicks context menu item on the column's header...

This is fine for the out-of-the-box ready-rolled column types like DataGridTextColumn, since they are bound, but the problem is that some of my columns are DataGridTemplateColumns, which are not bound.

private void GroupByField_Click (object sender, RoutedEventArgs e){
        MenuItem mi = (MenuItem)sender;
        ContextMenu cm = (ContextMenu) mi.Parent;
        DataGridColumnHeader dgch = (DataGridColumnHeader) cm.PlacementTarget;  
        DataGridBoundColumn dgbc = (DataGridBoundColumn) dgch.Column;
        Binding binding = (Binding) dgbc.Binding;
        string BoundPropName = binding.Path.Path;

        //Do stuff based on bound property name here...
    }

So, take for example my Name column... it's a DataGridTemplateColumn (since it has an image and some other stuff in there). Therefore, it is not actually bound to the 'Name' property... but I would like to be, so that the above code will work.

My question is two-part, really:

  1. Is it possible to make a DataGridTemplateColumn be BOUND, so that the above code would work? Can I bind it somehow to a property?

  2. Or do I need to something entirely different, and change the code above?

Thanks in advance!

AT

5条回答
唯我独甜
2楼-- · 2020-05-26 07:31

For me, ClipboardContentBinding of DataGridTemplateColumn is a solution:

Private Function FindBoundProperty(ByVal col As DataGridColumn) As String

    Dim boundColumn As DataGridBoundColumn = TryCast(col, DataGridBoundColumn)
    Dim boundPropertyName As String = ""
    Dim binding As Binding
    If col.DependencyObjectType.Name = "DataGridTextColumn" Then
        binding = TryCast(boundColumn.Binding, Binding)
        boundPropertyName = binding.Path.Path
    End If
    If col.DependencyObjectType.Name = "DataGridTemplateColumn" Then
        binding = TryCast(col.ClipboardContentBinding, Binding)
        boundPropertyName = binding.Path.Path
    End If
    Return boundPropertyName

End Function
查看更多
一夜七次
3楼-- · 2020-05-26 07:36

It's a tricky one. We achieved the binding by traversing to its grandparent UserControl (we had DataGrid inside a UserControl) and the UserControl was bound to a Presenter (Model in our case). In the code below, check the property SelectedItem of AutoCompleteBox placed inside the DataGridTemplateColumn.

<wpfToolkit:DataGridTemplateColumn  Header="{x:Static resources:Store.ItemNameC}" Width="0.60*">
  <wpfToolkit:DataGridTemplateColumn.CellEditingTemplate>
    <DataTemplate>
        <extended:HOAutoCompleteBox
                            IsTextCompletionEnabled ="True"
                            x:Name="ItemAutoCompleteBox"
                            Populating="ItemAutoCompleteBox_Populating"
                            DefaultType="HealthObject.ObjectModel.pSearchStockItemResult,HealthObject.ObjectModel"
                            Text="{Binding Path= ItemName, Mode=TwoWay}" 
                            <!--- **** HERE IS THE BINDING SAMPLE *****-->
            SelectedItem="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}},  Path=Model.SelectedStockItem, Mode=TwoWay}">
        </extended:HOAutoCompleteBox>
    </DataTemplate>
  </wpfToolkit:DataGridTemplateColumn.CellEditingTemplate>

</wpfToolkit:DataGridTemplateColumn>
查看更多
The star\"
4楼-- · 2020-05-26 07:40

You may use dgbc.ClipboardContentBinding;

查看更多
做自己的国王
5楼-- · 2020-05-26 07:44

Although you can't bind a template column, you can bind one of the controls held in that column. This is how I solved a similar problem:

<DataGridTemplateColumn Header="ColumnHeader">
     <DataGridTemplateColumn.CellTemplate>
           <DataTemplate>
                 <local:CustomisedUIElement Text="{Binding Path=PropertyToBindTo}"/>
           </DataTemplate>
     </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

If I've understood the initial example properly, this would mean changing the logic of the GroupByField_Click() method to check whether the sending column was a template column and then looking at the elements it contained to obtain the Binding object.

查看更多
劳资没心,怎么记你
6楼-- · 2020-05-26 07:47
  1. No, because DataGridTemplateColumn doesn't inherit from DataGridBoundColumn, so the cast to DataGridBoundColumn would fail.
    To make above code work all of your columns must inherit from DataGridBoundColumn abstract class. So making custom derived Column classes instead of DataGridTemplateColumn should work.

  2. You could simply populate a

    Dictionary<DataGridColumn, string> BoundPropName;

    on initialization and then do

    var propName = BoundPropName[dgch.Column]

查看更多
登录 后发表回答