XAML ListView How to style - wpf

An image is better than a thousand of words.
I have a list view Left image, and want to force my inner object (TextBlock) to use the full space of my ListViewItem, Right image.
How can i do to style it?
Here is my xaml
<ListView
x:Name="ListProperties"
Grid.Row="1"
ItemsSource="{Binding ImportarConfig.PropertiesList}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" Width="{Binding ElementName=ListProperties.Width}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<CheckBox IsChecked="{Binding IsOptional}" Grid.Column="1"/>
<TextBlock Text="{Binding ColumnName}" Style="{StaticResource BlockHeaderWarning}" AllowDrop="True" Drop="TextBlock_Drop" Width="{Binding ElementName=ListProperties.Width}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I tryed Changing Grid to Stackpanel but nothing happens

You need to use ItemContainerStyle and set your HorizontalAlignment and HorizontalContentAlignment to Stretch.
Something like:
<ListView
x:Name="ListProperties"
Grid.Row="1"
ItemsSource="{Binding ImportarConfig.PropertiesList}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" Width="{Binding ElementName=ListProperties.Width}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<CheckBox IsChecked="{Binding IsOptional}" Grid.Column="1"/>
<TextBlock Text="{Binding ColumnName}" Style="{StaticResource BlockHeaderWarning}" AllowDrop="True" Drop="TextBlock_Drop" Width="{Binding ElementName=ListProperties.Width}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
</ListView>

Related

Why TextWrapping for the TextBlock in the Grid works only if I specify TexBlock Width?

Why TextWrapping for the TextBlock in the Grid works only if I specify TexBlock Width?
When I remove TextBlock MaxWidth Property TextWrapping is not working.
Full code for ComboBox
<Window Height="600" Width="480">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" Grid.Column="0" ItemsSource="{Binding MyList}" SelectedIndex="0" x:Name="comboBox" HorizontalAlignment="Stretch" VerticalAlignment="Top">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="2" Text="{Binding Code}"></TextBlock>
<TextBlock Margin="2" Text="{Binding Name}"></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid ShowGridLines="False">
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="50"/>
<ColumnDefinition Name="Column1" MaxWidth="300"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Code}"/>
<TextBlock Grid.Column="1" MaxWidth="{Binding ElementName=Column1, Path=MaxWidth}" Text="{Binding Name}" TextWrapping="Wrap"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
</Grid>
</Window>
The reason is by defining your ColumnDefinition as Auto or * or not setting it at all you have nothing to limit the size available for your TextBlock to consume. So it would be expected behavior for the Text to not Wrap. So you'll have to define a Width or MaxWidth on either the ColumnDefinition or the TextBlock directly in order for wrapping to work.
Why TextWrapping for the TextBlock in the Grid works only if I specify TexBlock Width?
Because the Grid gets added to an invisible ScrollViewer when the ComboBox is opened. You could fix this and get the text to wrap by simply setting the ScrollViewer.HorizontalScrollBarVisibility attached property of the ComboBox to Disabled:
<ComboBox Grid.Row="0" Grid.Column="0" ItemsSource="{Binding MyList}"
SelectedIndex="0" x:Name="comboBox" HorizontalAlignment="Stretch"
VerticalAlignment="Top" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="2" Text="{Binding Code}"></TextBlock>
<TextBlock Margin="2" Text="{Binding Name}"></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Width="100" />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid ShowGridLines="False">
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="50"/>
<ColumnDefinition MaxWidth="300"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Code..."/>
<TextBlock Grid.Column="1"
Text="some long text some long text some long text some long text some long text"
TextWrapping="Wrap"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>

WPF ListboxItems with ItemContainerStyle become unselectable

I coded the following ListBoxItemStyle to be able to place multiple elements into the listboxitem:
<Style x:Key="lbWithButton" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{TemplateBinding Content}" Grid.Column="0"/>
<xctk:IntegerUpDown Minimum="0" Value="0" Maximum="1000" Grid.Column="1"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Unfortunately i cant select ListboxItems anymore.
This also happens with only the textblock inside the listboxitem.
Help would be appreciated!
You must use ItemTemplate instead of ItemContainerStyle:
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Content}" Grid.Column="0"/>
<xctk:IntegerUpDown Minimum="0" Value="0" Maximum="1000" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

WPF Multicolumn Combobox

I have the following data template used for a multicolumn combo box:
<DataTemplate x:Key="ShipViaKey">
<Grid Height="23" Width="Auto" ShowGridLines="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Code}"/>
<TextBlock Grid.Column="1" Text="{Binding Carrier}"/>
</Grid>
</DataTemplate>
The combo box is defined like this:
<ComboBox Grid.Row="0" Grid.Column="1" x:Name="CboShipVia" SelectedValue="{Binding FkCarrier, Mode=TwoWay}" SelectedValuePath="PkCarrier" IsEnabled="{Binding HasData}" ItemTemplate="{StaticResource ShipViaKey}"/>
This is all fine; except I want to only display the "Code" of the selected item in the combo box, not both values. Is there a way to do this?
Instead of ItemTemplate, use ItemContainerStyle:
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid Height="23" Width="Auto" ShowGridLines="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Code}"/>
<TextBlock Grid.Column="1" Text="{Binding Carrier}"/>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
Also, set DisplayMemberPath to Code property.
I came up with this solution that provides columns vertical alignment thanks to the SharedSizeGroup feature.
Resources:
<DataTemplate x:Key="advancedComboxItemDataTemplate">
<Grid Width="Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="A"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Caption}" Margin="5" Grid.Column="0" TextAlignment="Left"/>
<TextBlock Text="{Binding Description}" Margin="5" Grid.Column="1" TextAlignment="Left">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ComboBoxItem}, Path=IsSelected}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</DataTemplate>
<ItemsPanelTemplate x:Key="advancedComboxItemsPanelTemplate">
<StackPanel Grid.IsSharedSizeScope="True" IsItemsHost="True"/>
</ItemsPanelTemplate>
Usage:
<ComboBox Width="300"
ItemsSource="{Binding ReferentialData.BankReferences}"
SelectedItem="{Binding SelectedObject.PayTermBankReference}"
ItemTemplate="{StaticResource advancedComboxItemDataTemplate}"
ItemsPanel="{StaticResource advancedComboxItemsPanelTemplate}"/>

Combobox with itemcontainerstyle selected item background

I have a comobox defined as follows:
<ComboBox Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3" SelectedValue="{Binding Path=CurrentLineItem.Location, Mode=TwoWay}" SelectedValuePath="Location" DisplayMemberPath="Location" IsEnabled="{Binding Path=CurrentLineItem.Editing, Mode=OneWay}" ItemsSource="{Binding CurrentLineItem.LocationDetails}">
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="70"/>
</Grid.ColumnDefinitions>
<TextBlock Margin="5" Grid.Column="0" Text="{Binding Location, Mode=OneWay}"/>
<TextBlock Margin="5" Grid.Column="1" Text="{Binding OnHand, Mode=OneWay, StringFormat=\{0:N4\}}"/>
<TextBlock Margin="5" Grid.Column="2" Text="{Binding Allocated, Mode=OneWay, StringFormat=\{0:N4\}}"/>
<TextBlock Margin="5" Grid.Column="3" Text="0.0000"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
This is working fine except that I want the selected item to be highlighted with a blue background. How do I do this?
<ComboBox Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3" SelectedValue="{Binding Path=CurrentLineItem.Location, Mode=TwoWay}" SelectedValuePath="Location" DisplayMemberPath="Location" IsEnabled="{Binding Path=CurrentLineItem.Editing, Mode=OneWay}" ItemsSource="{Binding CurrentLineItem.LocationDetails}">
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="70"/>
</Grid.ColumnDefinitions>
<TextBlock Margin="5" Grid.Column="0" Text="{Binding Location, Mode=OneWay}"/>
<TextBlock Margin="5" Grid.Column="1" Text="{Binding OnHand, Mode=OneWay, StringFormat=\{0:N4\}}"/>
<TextBlock Margin="5" Grid.Column="2" Text="{Binding Allocated, Mode=OneWay, StringFormat=\{0:N4\}}"/>
<TextBlock Margin="5" Grid.Column="3" Text="0.0000"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=IsSelected}" Value="True">
<Setter Property="Background" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>

How to remove the left-hand blue line on custom selected styled Listbox items?

I found this code which replaces the default select style with a custom style for the select ListBoxItem in a ListBox. However, there is still a little blue line on the left from the default style which I can't remove with any padding or margin changes.
How can I remove that blue line and completely determine the style of the selected ListBoxItem?
alt text http://tanguay.info/web/external/blueLineLeft.png
<Window x:Class="CodingContext.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CodingContext"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<DataTemplate x:Key="ItemTemplate" DataType="{x:Type local:Person}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=Name, StringFormat=Name: \{0\}}" />
<TextBlock Grid.Column="1" Text="{Binding Path=Age, StringFormat=Age: \{0\}}" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="SelectedTemplate" DataType="{x:Type local:Person}">
<Grid Background="Yellow">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Foreground="Black" Grid.Row="0" Grid.Column="0" Text="Person" FontSize="14" FontWeight="Bold" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding Path=Name, StringFormat=Name: \{0\}}" />
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Age, StringFormat=Age: \{0\}}" />
<TextBlock Grid.Row="2" Grid.Column="0" Text="Address" FontSize="14" FontWeight="Bold" />
<StackPanel Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal">
<TextBlock Text="{Binding Address}" />
<TextBlock Text="{Binding City, StringFormat= \{0\}}" />
<TextBlock Text="{Binding State, StringFormat= \{0\}}" />
<TextBlock Text="{Binding Zip, StringFormat= \{0\}}" />
</StackPanel>
</Grid>
</DataTemplate>
<Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
<Setter Property="ContentTemplate" Value="{StaticResource ItemTemplate}" />
<Setter Property="Margin" Value="5" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource SelectedTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<ListBox HorizontalContentAlignment="Stretch" Margin="10" x:Name="lstPeople" ItemsSource="{Binding People}" ItemContainerStyle="{StaticResource ContainerStyle}" />
</Window>
I'm pretty sure this is a bug, as several people have had this issue with the ListBoxItem template.
To fix, just add:
<Setter Property="Padding" Value="0,0,0,0"/>
to your ContainerStyle template. It's originally 2,0,0,0.
Have a look at this answer to a similar question. Basically, if you want to restyle the ListBox so that selected items have a different background colour, it's easier to simply change the "HighlightBrush" colour so that the selected item uses the colour you want.

Resources