I'd like the users of my program to be able to decide for themselves, which columns they'd like to see in my ListView/GridView.
For that I created two attached properties for GridViewColumn
, one is called IsColumnVisible
of type Boolean
(toggling visibility of the column on and off) and the other one is called LastWidth
of type Double
(holding the width of this column when it was last visible).
The property IsColumnVisible
does have an OnChangedCallback
.
When the property is set to False
, I save the current width of the column in my property LastWidth
and set the current width to 0.
When the property is set to True
, I get the last width of the column from my property LastWidth
and set the current width to that value.
This works so far, but with the flaw, that one can resize the hidden columns with the mouse to be visible again. So, if you have three columns and you hide the middle one, resizing the first one with the mouse ends up in making the second column visible again.
To get rid of that I wanted to set the IsEnabled
state of the headers of the hidden columns to False
and that's where the problem begins.
Let's say my columns are defined in XAML like this (columns 1 and 4 visible, columns 2 and 3 hidden):
<GridView AllowsColumnReorder="True">
<GridViewColumn Header="Column 1" Width="50" DisplayMemberBinding="{Binding Column1}" local:GridViewColumnConfig.IsColumnVisible="True" />
<GridViewColumn Header="Column 2" Width="50" DisplayMemberBinding="{Binding Column2}" local:GridViewColumnConfig.IsColumnVisible="False" />
<GridViewColumn Header="Column 3" Width="50" DisplayMemberBinding="{Binding Column3}" local:GridViewColumnConfig.IsColumnVisible="False">
<GridViewColumn.Header>
<GridViewColumnHeader Content="Column 4" />
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn Header="Column 4" Width="50" DisplayMemberBinding="{Binding Column4}" local:GridViewColumnConfig.IsColumnVisible="True" />
</GridView>
Since the default value of my property IsColumnVisible
is True
, my OnChangedCallback
of this property only runs for columns 2 and 3.
I have an object of type GridViewColumn
in the OnChangedCallback
and to be able to set the IsEnabled
state of the column header I need to determine the GridViewColumnHeader
of my GridViewColumn
.
A GridViewColumn
has a property Header
of type Object
. In case of column 2 this property contains the String
"Column 2", in case of column 3 this property is Nothing
.
Is there any way to get the header of my GridViewColumn
as a GridViewColumnHeader
object?
In case of column 2 I could create a GridViewColumnHeader
object myself, set it's Content
to the value of the Header
property and then set the Header
property to this object.
But I'd rather not do those changes if I don't have to.
In case of column 3 there already should be a GridViewColumnHeader
object somewhere (since I defined it in XAML), but I can't find it.
I already tried to walk the Visual Tree, but since GridViewColumn
is not a Visual
or a Visual3D
, that's not possible.
Any ideas? Thank you.
Is there any way to get the header of my
GridViewColumn
as aGridViewColumnHeader
object?
The easiest way to do this would be to set the value of your custom attached property after you have set the value of the Header
property.
You could do this if you switch to using element syntax:
<GridViewColumn Width="50" DisplayMemberBinding="{Binding Column3}" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<GridViewColumn.Header>
<GridViewColumnHeader Content="Column 4" />
</GridViewColumn.Header>
<local:GridViewColumnConfig.IsColumnVisible>
<sys:Boolean>False</sys:Boolean>
</local:GridViewColumnConfig.IsColumnVisible>
</GridViewColumn>
Then you will be able to simply cast the Header
property to a GridViewColumnHeader
in your PropertyChangedCallback
:
Private Shared Sub OnPropertyChanged(d As GridViewColumn, e As DependencyPropertyChangedEventArgs)
Dim header = TryCast(d.Header, GridViewColumnHeader)
'...
End Sub