Populate ComboBox in GridView header with column data - wpf

I want to have a ComboBox in the header cells of my GridView (currently inside of a ListView) populated with the data from that column. To be used a bit like the 'auto filter' feature in Excel.
The problem I have is I can't get to the data for the column from inside the header cell. At the moment, I have something like this:
<Grid>
<Grid.Resources>
<DataTemplate x:Key="headerTemplate">
<StackPanel>
<ComboBox></ComboBox>
<TextBlock FontSize="16" Text="{Binding}" Grid.Row="1" HorizontalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</Grid.Resources>
<ListView Width="400" Height="200">
<ListView.View>
<GridView ColumnHeaderTemplate="{StaticResource headerTemplate}">
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Namespace" DisplayMemberBinding="{Binding Namespace}"/>
</GridView>
</ListView.View>
<x:Type TypeName="Visual"/>
<x:Type TypeName="UIElement"/>
<x:Type TypeName="FrameworkElement"/>
</ListView>
</Grid>
But I'm not sure how to get the data to populate the combo boxes in the header. What's the best way of doing this?

A quick and dirty way would be something like this:
<Grid.Resources>
<DataTemplate x:Key="headerTemplate">
<StackPanel>
<ComboBox ItemsSource="{Binding Path=Items, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListView}}}" DisplayMemberPath="{Binding}"/>
<TextBlock FontSize="16" Text="{Binding}" Grid.Row="1" HorizontalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</Grid.Resources>
If you really need a filter-like list, you'll have to figure out how to get distinct values only.

Related

Binding to elements in WPF GridViewHeader doesn't work

I'm trying to create a custom header for a ListView / GridView where the user can easily filter items using Text inputs:
I've created DependencyProperties on the UserControl's code-behind and are binding the Xaml datacontext to itself (name=root). The binding i'm having trouble with is the TextBox inside the Header - it simply doesn't work. If i set a 'ModelVariantId' to "Whatever" it doesn't show and likewize i don't get any PropertyChanged events when writing in it..
I've found -some- similar sounding questions on the internet but nothing exactly matching.
<ListView ItemsSource="{Binding ElementName=root, Path=CombinedCarModels}">
<ListView.View>
<GridView>
<GridViewColumn Width="120" DisplayMemberBinding="{Binding ModelVariantId}">
<GridViewColumn.Header>
<GridViewColumnHeader HorizontalContentAlignment="Stretch">
<StackPanel>
<Label>ModelVariantId</Label>
<TextBox Text="{Binding ElementName=root,
Path=CarModelFilter.ModelVariantId, Mode=TwoWay}" />
</StackPanel>
</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
If you define a HeaderTemplate, this binding should work:
Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl},
Path=CarModelFilter.ModelVariantId, Mode=TwoWay}"
XAML:
<GridViewColumn.HeaderTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" HorizontalAlignment="Stretch">ModelVariantId</Label>
<TextBox Grid.Row="1" HorizontalAlignment="Stretch"
Text="{Binding ElementName=root, Path=CarModelFilter.ModelVariantId, Mode=TwoWay}" />
</Grid>
</DataTemplate>
</GridViewColumn.HeaderTemplate>
There is no element named "root" in the same naming scope as the header, but you should be able to bind to a parent element in the visual tree using the RelativeSource property.
This assumes that the parent UserControl has a CarModelFilter property.

Putting ComboBox in a one special row in ListView in WPF

How to put a Combobox to a special row of a listview (WPF, VB.net)?
There is a ListView that has two columns. The columns are "Parameter" and "Values". The second column has different types (such as numbers, strings and "Selectable values") and is editable. The "Selectable values" have to appear in a Combobox.
One of the ways that I think about, is conditional XAML tags (I don`t know if it is possible or not ?) .
I tried this code but it shows Combobox for all rows in listview :
<ListView x:Name="listView"
HorizontalAlignment="Left"
Height="237"
Margin="40,34,0,0"
VerticalAlignment="Top"
Width="447"
ItemsSource="{Binding Values}">
<ListView.View>
<GridView>
<GridViewColumn Header="Parameter"
DisplayMemberBinding="{Binding Path=LName}"
Width="100" />
<GridViewColumn Header="Value"
Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=ListView}, Path=ItemsSource}"
Width="120">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Type}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
I only want to use Combobox for one row while the type of the rest of rows are double or string. How can I do this?

WPF GridView Column width on different PC resolution

How to set width for GridViewColumn that it will work all time on different resolution? For example I have this listView:
And then I open it in another PC (with different resolution) I get this view :
It is missing few column.
I copy one of my column xaml code :
<ListView x:Name="sample" Margin="30,98.4,362,150" ScrollViewer.VerticalScrollBarVisibility="Visible"
AlternationCount="2" ScrollViewer.CanContentScroll="False">
<ListView.View>
<GridView>
<GridViewColumn>
<!-- 1st Column-->
<GridViewColumnHeader Content="Product" Margin="10,0,0,0"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Grid Height="42px">
<TextBlock Text="{Binding odd}" VerticalAlignment="Center"
Width="600" TextAlignment="Left"/>
</Grid>
<TextBlock Foreground="#B30C0C" Height="42px" Padding="10,5,0,0" Text="{Binding discounText}"
Visibility="{Binding IsDiscount, Converter={StaticResource VisibilityConverter}}" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn >
How you see I write width parameter in TextBlock. How I have to rewrite it or maybe make some changes in code?
Use relative sizing (with *) instead of fixed values. For that, you'll have to move your Width setting from the TextBlock to the Column itself:
<GridViewColumn Width="600*">
<!-- 1st Column-->
<GridViewColumnHeader Content="Product" Margin="10,0,0,0"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Grid Height="42px">
<TextBlock Text="{Binding odd}" VerticalAlignment="Center"
TextAlignment="Left"/>
</Grid>
<TextBlock Foreground="#B30C0C" Height="42px" Padding="10,5,0,0" Text="{Binding discounText}"
Visibility="{Binding IsDiscount, Converter={StaticResource VisibilityConverter}}" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
I've set 600* because the fastest way to keep the current proportions is keeping the same values you have right now, but adding the *. But that number can be a lot lower, since it just defines the proportion between columns... Feel free to toy with the values to get the effect you want.

Treeview shows random extra space

I have a treeview in wpf that is showing some strange behavior (at least I think it's strange). I don't see anywhere I can attach an image but basically on some of the items it looks like it's double spaced or has an extra 3px or so margin and on some it looks like it's single spaced. Here is the XAML defining it:
<TreeView Margin="5,0,0,5" ItemsSource="{Binding SortedCategories}" HorizontalContentAlignment="Stretch">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type COBie:CategoryData}" ItemsSource="{Binding SortedTypes}">
<CheckBox IsChecked="{Binding AnyChecked, Mode=TwoWay}" Content="{Binding CategoryName}" IsEnabled="{Binding HasTypes}" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type COBie:InstanceData}">
<CheckBox IsChecked="{Binding isChecked, Mode=TwoWay}" Content="{Binding ElemID}" />
</DataTemplate>
<DataTemplate DataType="{x:Type COBie:TypeData}">
<TreeViewItem IsEnabled="{Binding HasInstances}" HorizontalContentAlignment="Stretch">
<TreeViewItem.Header>
<CheckBox IsChecked="{Binding isChecked, Mode=TwoWay}" Content="{Binding ElemName}" />
</TreeViewItem.Header>
<ListView ItemsSource="{Binding SortedInstances}">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding isChecked, Mode=TwoWay}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding ElemID}" />
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding ElemName}" />
<GridViewColumn Header="Mark" DisplayMemberBinding="{Binding Mark}" />
<GridViewColumn Header="Room" DisplayMemberBinding="{Binding RoomDisplay}" />
</GridView>
</ListView.View>
</ListView>
</TreeViewItem>
</DataTemplate>
</TreeView.Resources>
</TreeView>
The only other relevant style that would apply is:
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding IsExpanded}" />
</Style>
I don't see anywhere that defines a margin at all and even if it did all of the elements are of the same class so it should apply to all equally.
Anyone know what is going on?
I had the same issue, that there were seemingly random gaps.
After looking closer I found out that the gaps appeared around items, that have underscore(s) in the name.
If you put the string directly in the content property of the CheckBox and it contains underscores, the CheckBox will surround a TextBlock with a Control named AccessText, probably to support short cut keys (similar to underscores in Button's Content property).
Now for some reason the Margin of the Checkbox is set on the TextBlock perfectly fine, if there is no AccessText involved, but is not set on the TextBlock inside the AccessText. This way the TextBlock inside the AccessText will have default TextBlock Style, which in my case was with Margin=5.
I guess in your case it must be a closely related issue.

How to set tabindex in dynamic generated textbox inside listView in wpf

We built our user interface from XML definitions (not XAML) but underneath we use a WPF to present the UI. That is at runtime, we create the WPF UI based on our XML definition.
<ListView ItemsSource="{Binding}" Width="400px" IsSynchronizedWithCurrentItem="True" HorizontalAlignment="Left" Name="ListView"
ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled" Grid.ColumnSpan="3"
SelectionChanged="ListView_SelectionChanged" BorderThickness="0" IsTabStop="False">
<ListView.View>
<GridView x:Name="grid">
<GridViewColumn Width="100px">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=ModuleName}" Width="100px" Foreground="Black" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="200px">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=ModuleUserCount, TargetNullValue=''}" MaxLength="6" Name="txtModuleUserCount" KeyDown="txtModuleUserCount_KeyDown" MinWidth="180" MaxWidth="200" BorderBrush="Gray"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</ListView.View>
</ListView>
I generate 4 module through XML SO UI have four TextBox in these dynamic TextBox tabIndex is not working. I tried KeyboardNavigation.TabNavigation="Cycle" but it's not working. How to make tab navigation work for this layout?
I know its too too late, but I would like to answer. I had the same problem. I tried following way and it resolved my problem: Set:
KeyboardNavigation.TabIndex="10"
or whatever value you require in ListView itself.

Resources