Introduction
I had run into an issue where I wanted to use a Combo box in the header of a GridView
control.
This control would be used for filtering the data in the columns. I wanted specific text (Column Headers) to appear in the combobox and when the client clicked anywhere in the combobox, the drop down would appear and the user can click the item to filter on.
Once the user clicked the desired filter item, the combobox would close and the header would be back.
Background
There are a few ways of doing this, but the drop down needed to be fully clickable, and I did not want the I style cursor. Nor did I want the text to be highlighted once clicked on the combobox.
How did I resolve this?
I added the combo boxes to the headers template to the gridview
and then I styled most of it into place.
Please see the below code.
Using the Code
First, I created the ListView
and morphed that to a gridview
:
<ListView DockPanel.Dock="Top" Name="ListView_DataQuery">
<ListView.View>
<GridView>
<GridViewColumn x:Name="ComputerName"
DisplayMemberBinding="{Binding ComputerName}"
Header="Computer Name"></GridViewColumn>
<GridViewColumn x:Name="Name"
DisplayMemberBinding="{Binding Name}"
Header="Property Name"></GridViewColumn>
<GridViewColumn x:Name="Type"
DisplayMemberBinding="{Binding Type}"
Header="Property Type"></GridViewColumn>
<GridViewColumn x:Name="Value"
DisplayMemberBinding="{Binding Value}"
Header="Property Value"></GridViewColumn>
<GridViewColumn x:Name="Instance"
DisplayMemberBinding="{Binding RelPath}"
Header="Instance"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
A Simple List View/Grid View with member displayed bindings
Now some styling to add some epic awesomeness.
<Style TargetType="GridViewColumnHeader" >
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<DockPanel>
<Grid>
<ComboBox Background="Transparent"
Foreground="Black"
BorderBrush="Transparent"
MaxDropDownHeight="8000"
Name="ComboBox_DataQuery_SelectedItem"
MinWidth="120"
DockPanel.Dock="Right"
HorizontalAlignment="Right"
SelectedItem="{Binding Filter_ListView_DataQuery}"
SelectedIndex="{Binding FilterIndex_ListView_DataQuery}"
Drop="ComboBox_GridView_Filter_DropDownClosed"
DropDownOpened="ComboBox_GridView_Filter_DropDownOpen"
DropDownClosed="ComboBox_GridView_Filter_DropDownClosed" Uid="{Binding}"
/>
<Label Margin="0,0,20,0"
DockPanel.Dock="Left"
HorizontalContentAlignment="Right"
Background="Transparent"
BorderBrush="Transparent"
IsHitTestVisible="False"
Focusable="False"
Content="{Binding}"/>
</Grid>
</DockPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
A lot going on here, but basically what this has done is put a Label
underneath the combobox.
I have set the background
property to transparent
so we can see the text, and the text is bound to the column headers of the gridview.
The Selected Item and the Selected index have been bound to public
properties, this is for functionality.
There are some Events as well for more functionality, in a perfect world these events would be bound as well.
So now we have dropdown comboboxes that sort of work.
But there is code required:
private void ComboBox_GridView_Filter_DropDownClosed(object sender, EventArgs e)
{
ComboBox ComboBoxDroppedDown = (ComboBox)sender;
ComboBoxDroppedDown.SelectedIndex = -1;
}
When you close the combo box, the value that you clicked will be removed, this is so that you don't have overlapping texts..
This is basically all you require for the visual effects.
Points of Interest
In my specific case, I used a DataTable
to enter data into my Gridview. This helped in the filtering and whatever. However, having a combobox that you can click, that uses the same cursor and drops down but still acts like a header.
History
Yes, I know this isn't strict to the MVVM model, however it is just an example of how to style the button to how I needed it. I'm sure that you can massage it to how you might require it.
This is my first tip. I hope it helps you because I searched for a fair while and went asking for help and eventually sorted it out.