There is no universal way to find GridViewColumnHeader from GridViewColumn that would be convenient and doesn’t impact performance. But in different situations you can choose appropriate method from those described below. They are arranged below in descending order from architectural point of view from more convenient to less one. “From architectural point of view” means: universal for all projects and solutions, convenient for those who will use it, and has minimum impact to performance
GridViewColumnHeader from GridViewColumn – Using Attached Properties
This is the most universal way that have no impact to performance.
The idea is based on GridViewColumnHeader’s knowledge of it’s GridViewColumn via Column property. If we can catch the moment when this Column property is changed we can set some GridViewColumn’s attached property to our GridViewColumnHeader object. Let’s look to code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
public static class GridViewExtension { /// <summary> /// Synthetic attached property for wiring up GridViewColumn with it's GridViewColumnHeader. /// Serves for catching the moment when GridViewColumnHeader.Column has changed. /// </summary> public static readonly DependencyProperty BoundGridViewColumnProperty = DependencyProperty.RegisterAttached("BoundGridViewColumn", typeof(GridViewColumn), typeof(GridViewExtension), new UIPropertyMetadata(null, BoundGridViewColumnPropertyChanged)); private static void BoundGridViewColumnPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { var gridViewColumnHeader = o as GridViewColumnHeader; if (gridViewColumnHeader == null || gridViewColumnHeader.Column == null) return; // Set attached property Column.BoundGridViewColumnHeader SetBoundGridViewColumnHeader(gridViewColumnHeader.Column, gridViewColumnHeader); } /// <summary> /// This property "attached" to GridViewColumn and contains GridViewColumnHeader instance /// </summary> public static readonly DependencyProperty BoundGridViewColumnHeaderProperty = DependencyProperty.RegisterAttached("BoundGridViewColumnHeader", typeof(GridViewColumnHeader), typeof(GridViewExtension), new PropertyMetadata(null)); public static GridViewColumnHeader GetBoundGridViewColumnHeader(DependencyObject obj) { return (GridViewColumnHeader)obj.GetValue(BoundGridViewColumnHeaderProperty); } public static void SetBoundGridViewColumnHeader(DependencyObject obj, GridViewColumnHeader value) { obj.SetValue(BoundGridViewColumnHeaderProperty, value); } |
With next step we need to bound our synthetic attached property to real Column property.
1 2 3 4 5 6 |
<!-- GridViewColumnHeader style --> <Style TargetType="{x:Type GridViewColumnHeader}"> ... <Setter Property="myNamespace:GridViewExtension.BoundGridViewColumn" Value="{Binding RelativeSource={RelativeSource Self}, Path=Column, Mode=OneWay}"/> ... </Style> |
When the GridViewColumnHeader.Column property is changed, we in BoundGridViewColumnPropertyChanged method set BoundGridViewColumnHeader attached property for Column.
So now we can get GridViewColumnHeader from every GridViewColumn like this:
1 |
var gridViewColumnHeader = GridViewExtension.GetBoundGridViewColumnHeader(column); |
Using your knowledge about GridViewColumn style
If you sure that your GridViewColumn style always contains GridViewColumnHeader:
1 2 3 4 5 |
<GridViewColumn x:Name="myColumn"> <GridViewColumnHeader> My Header </GridViewColumnHeader> </GridViewColumn> |
than you can get GridViewColumnHeader very easy:
1 |
var gridViewColumnHeader = (GridViewColumnHeader)column.Header; |
But if the header is set like this
1 2 3 |
<GridViewColumn x:Name="myColumn"> My Header </GridViewColumn> |
than column.Header will return “My Header” of type string, not GridViewColumnHeader.
Using Visual Tree
You can use this way to find visual children of type GridViewColumnHeader for your GridViewColumn. For example, as here http://stackoverflow.com/questions/974598/find-all-controls-in-wpf-window-by-type
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject { if (depObj != null) { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) { DependencyObject child = VisualTreeHelper.GetChild(depObj, i); if (child != null && child is T) { yield return (T)child; } foreach (T childOfChild in FindVisualChildren<T>(child)) { yield return childOfChild; } } } } |
Next line returns GridViewColumnHeader if it exists or null:
1 |
GridViewColumnHeader header = FindVisualChildren<GridViewColumnHeader>(column).FirstOrDefault(); |
class GridViewExtension is not fully presented and the SetValue and GetValue methods for BoundGridViewColumnProperty are missing. But otherwise this saved my day. 🙂