How do I get the ActualWidth of the GridViewColumn - wpf

I have the following XAML:
<GridView x:Key="myGridView">
<GridViewColumn CellTemplate="{StaticResource myTemplate}"/>
</GridView>
<DataTemplate x:Key="myTemplate">
<ContentPresenter Content="{Binding}"/>
</DateTemplate>
When I use it, I want the contentpresenter to have the same width as the GridViewColumn. So far, I've tried using the RelativeSource binding but I can't seem to get the GridViewColumn at all.
How do I get the ActualWidth from the parent GridViewColumn from the ContentPresenter in my DataTemplate?

The problem with GridView is that there is no notion of cells as visual elements in the generated control hierarchy. In order for your ContentPresenter to be wide as the column you should set the HorizontalContentAlignment property of the ListViewItem to Stretch. This way the ContentPresenter will stretch to the available width, which is the width of the column.
Here is a sample XAML which illustrates this:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Grid.Resources>
<DataTemplate x:Key="leftTemplate">
<ContentPresenter HorizontalAlignment="Left" Content="{Binding}"/>
</DataTemplate>
<DataTemplate x:Key="rightTemplate">
<ContentPresenter HorizontalAlignment="Right" Content="{Binding}"/>
</DataTemplate>
<GridView x:Key="myGridView">
<GridViewColumn Width="150" CellTemplate="{StaticResource rightTemplate}" Header="Right"/>
<GridViewColumn Width="150" CellTemplate="{StaticResource leftTemplate}" Header="Left"/>
</GridView>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</Grid.Resources>
<ListView Margin="10" View="{StaticResource myGridView}">
<ListViewItem Content="item 1"/>
<ListViewItem Content="item 2"/>
<ListViewItem Content="item 3"/>
<ListViewItem Content="item 4"/>
<ListViewItem Content="item 5"/>
</ListView>
</Grid>
</Page>

Related

How to Group Listview items that are added through XAML?

I have a Listview in XAML with few Listview Items that are added through XAML only and my listview has no other Items source.I want to group the items into two group.My Listview code is something like this
<ListView Name="List">
<ListViewItem Content="Apple" />
<ListViewItem Content="Orange" />
<ListViewItem Content="Tomato" />
<ListViewItem Content="Potato" />
<ListView />
I want to group them into two sets .Is this possible.
I would say if you want to group items in ListView you will not go around the CollectionViewSource. It's easier to fill it in ViewModel, but if you haven't VM you can also create one in XAML.
<StackPanel>
<StackPanel.Resources>
<x:Array x:Key="arr" Type="{x:Type ListViewItem}">
<ListViewItem Content="Orange" Tag="Meal"/>
<ListViewItem Content="Apple" Tag="Meal"/>
<ListViewItem Content="Cat" Tag="Pets"/>
<ListViewItem Content="Dog" Tag="Pets"/>
<ListViewItem Content="Fish" Tag="Diverse"/>
<ListViewItem Content="Duck" Tag="Diverse"/>
</x:Array>
<CollectionViewSource x:Key="CVS" Source="{DynamicResource arr}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Tag" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</StackPanel.Resources>
<ListView ItemsSource="{Binding Source={StaticResource CVS}}">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Label Content="{Binding Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</StackPanel>

How to bind button inside listview

I cant bind button inside listview to the GoToTask property, every other binding, include second button in the grid is work well.
<Grid>
<ListView ItemsSource="{Binding Projects}" SelectedItem="{Binding SelectedProject, Mode=TwoWay}" Grid.Row="1">
<ListView.Resources>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Visibility" Value="Collapsed"/>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Go">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Content="Go" Command="{Binding Path=GoToTasks, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<Button Height="20" Width="50" HorizontalAlignment="Right" Command="{Binding GoToTasks}" Content="Go"/>
</Grid>
Everything is inside UserControl.
What is wrong?
GridViewColumn is not part of VisualTree and therefore you are not allowed to use FindAncestor.
Similar here. Try ElementName, as far as I remember it uses LogicalTree.

Why doesn't my text block style get applied?

I have a style created in my windows resources area:
<Style TargetType="TextBlock">
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
</Style>
I thought this meant that all text blocks would have this style, so when I create my list view column:
<GridViewColumn>
<GridViewColumnHeader Content="Source"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Source, Mode=OneWay}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
The ellipsis style is NOT applied to the text block in the column.
If I name the style with x:Key, then use Style={StaticResource xxx} then it works - why doesn't the unnamed approach work?
Here's the complete window XAML:
<Window x:Class="ListViewStyle.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="TextBlock">
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
</Style>
</Window.Resources>
<ListView ItemsSource="{Binding Rows}">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumnHeader Content="Source"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Source, Mode=OneWay}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<GridViewColumnHeader Content="Primary"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Primary, Mode=OneWay}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<GridViewColumnHeader Content="Secondary"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Secondary, Mode=OneWay}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Window>
You may be defining another TextBlock style, closer to the TextBlock itself.
The way WPF searches for a style starts with the item to be styled. If it sets the Style property, then it uses that. Otherwise, it checks the parent's resources, then its grandparent's resources, and so on, using the first style it finds. If it doesn't find a style in your application it uses the default style.
There is probably a TextBlock style in one of the TextBlock's ancestors. If it finds a style there, it won't use the one at the window level.
You can specify that one style is based on another, with the BasedOn property.

Make WPF ComboBoxes fill a whole column width

I'm having problems making a ComboBox stretch to fill the whole column width in a GridViewColumn. It should also resize when the column is resized.
In the following example I have a StackPanel with a ComboBox inside. This is set to stretch and will in fact stretch to fill the StackPanel width.
Then I add a ListView with one column, containing a StackPanel with a ComboBox. Both the StackPanel and the ComboBox are set to stretch, but they don't. I use background colors to identify the size of the StackPanels, and there is no red unless I set a width or add elements to the ComboBox such that it needs more width.
I also tried playing around with the HorizontalContentAlignment property without success.
<StackPanel Height="59" Margin="45,12,38,0" VerticalAlignment="Top" Background="Green">
<ComboBox HorizontalAlignment="Stretch" />
</StackPanel>
<ListView x:Name="MyListView" Margin="0,106,0,0">
<ListView.View>
<GridView>
<GridViewColumn Header="Num" Width="70">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Background="red" Orientation="Horizontal" HorizontalAlignment="Stretch">
<ComboBox HorizontalAlignment="Stretch" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
<ListViewItem></ListViewItem>
</ListView>
Try setting the Style of the ListViewItem. I also removed your StackPanel.
<ListView x:Name="MyListView" Margin="0,106,0,0">
<ListView.Resources>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Header="Num" Width="170">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
<ListViewItem></ListViewItem>
</ListView>

Populate ComboBox in GridView header with column data

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.

Resources