Setting ListView Background - wpf

I hope to set the background with different brush, however, it doesn't work. No error, No warnings.
In my code, I hope make rows in ListView have different backgrounds, So, I define a Style for ListViewItem, but it can't know now. While I debug the code, I could step into local:NumberConverter:Convert(object value, Type targetType, object parameter, CultureInfo culture), however, the backgrounds of rows keep its original colors.
<UserControl x:Class="demo05_wpf02_binding.TabControl2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:demo05_wpf02_binding"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<Style x:Key="BookListStyle" TargetType="{x:Type ListViewItem}">
<Style.Resources>
<LinearGradientBrush x:Key="ProfitBrush" StartPoint="0.2,0" EndPoint="0.8,1">
<GradientStop Offset="0.3" Color="LavenderBlush" />
<GradientStop Offset="0.7" Color="CornflowerBlue" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="LossBrush" StartPoint="0.2,0" EndPoint="0.8,1">
<GradientStop Offset="0.3" Color="LightYellow" />
<GradientStop Offset="0.7" Color="LightGoldenrodYellow" />
</LinearGradientBrush>
<local:NumberConverter x:Key="numConverter" />
</Style.Resources>
<Style.Triggers>
<DataTrigger Binding="{Binding Title, Converter={StaticResource numConverter}}" Value="0" >
<Setter Property="Background" Value="{StaticResource ProfitBrush}" />
</DataTrigger>
<DataTrigger Binding="{Binding Title, Converter={StaticResource numConverter}}" Value="1" >
<Setter Property="Background" Value="{StaticResource LossBrush}" />
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<DockPanel>
<ListView Name="ListView01" ItemContainerStyle="{StaticResource BookListStyle}" ItemsSource="{Binding}" Margin="5">
<ListView.View>
<GridView>
<GridViewColumn Header="Title" DisplayMemberBinding="{Binding Title}" Width="80" />
<GridViewColumn Header="Publisher" DisplayMemberBinding="{Binding Publisher}" Width="100" />
<GridViewColumn Header="ISBN" DisplayMemberBinding="{Binding ISBN}" Width="100" />
</GridView>
</ListView.View>
</ListView>
</DockPanel>
</UserControl>

Your problem must lie in your Converter. If you removed the Converter, then your XAML would work just fine as it is if your data items had Title values of 1 and 0.
<Style x:Key="BookListStyle" TargetType="{x:Type ListViewItem}">
<Style.Resources>
<LinearGradientBrush x:Key="ProfitBrush" StartPoint="0.2,0" EndPoint="0.8,1">
<GradientStop Offset="0.3" Color="LavenderBlush" />
<GradientStop Offset="0.7" Color="CornflowerBlue" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="LossBrush" StartPoint="0.2,0" EndPoint="0.8,1">
<GradientStop Offset="0.3" Color="LightYellow" />
<GradientStop Offset="0.7" Color="LightGoldenrodYellow" />
</LinearGradientBrush>
</Style.Resources>
<Style.Triggers>
<DataTrigger Binding="{Binding Title}" Value="0" >
<Setter Property="Background" Value="{StaticResource ProfitBrush}" />
</DataTrigger>
<DataTrigger Binding="{Binding Title}" Value="1" >
<Setter Property="Background" Value="{StaticResource LossBrush}" />
</DataTrigger>
</Style.Triggers>
</Style>
So look closely at the code in your Converter... put a breakpoint there and step through the code until you find your problem. One other thing to note is that your LossBrush is very hard to see... maybe a stronger colour would help, even if only used when testing.

Related

Wpf tree-view two-way binding not working when using custom style for TreeViewItem

I tried to set up a custom styled treeview that does "just in time" loading by two-way binding the expanded property to a similar property in the view-model. The style and functionality aspects work fine on their own, but not when put together.
When I do it like this the functionality is there:
<TreeView Name="treeView" ItemsSource="{Binding}" Grid.Column="0">
<TreeView.Resources>
<ResourceDictionary Source="GroupedTreeViewItemStyle.xaml"/>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding Expanded, Mode=TwoWay}"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
But when I add the BasedOn to use my custom style it does no longer load any nodes.
I use my style by replacing the above style definition with the following:
<Style TargetType="TreeViewItem" BasedOn="{StaticResource GroupedTreeViewItemStyle}">
And here is my custom style based on this tutorial:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:this="*******namespace omitted*******">
<!-- This Style redefines the ControlTemplate used by TreeViewItems and
also provides a different itemspanel for their child items. -->
<Style TargetType="TreeViewItem" x:Key="GroupedTreeViewItemStyle">
<Style.Resources>
<LinearGradientBrush x:Key="ItemAreaBrush" StartPoint="0.5, 0" EndPoint="0.5, 1" Opacity="1">
<GradientStop Color="#fff" Offset="0" />
<GradientStop Color="#f2fcfe" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="SelectedItemAreaBrush" StartPoint="0.5, 0" EndPoint="0.5, 1" Opacity="1">
<GradientStop Color="#fff" Offset="0" />
<GradientStop Color="#f2fcfe" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ItemBorderBrush" StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Color="#243B55" Offset="0" />
<GradientStop Color="#141E30" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="SelectedItemBorderBrush" StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Color="#243B55" Offset="0" />
<GradientStop Color="#141E30" Offset="1" />
</LinearGradientBrush>
<DropShadowBitmapEffect x:Key="DropShadowEffect" />
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<Grid Margin="8,4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- This Border contains elements which display
the content and child items of the TreeViewItem. -->
<Border Name="Bd"
Background="{StaticResource ItemAreaBrush}"
BorderBrush="{StaticResource ItemBorderBrush}"
BorderThickness="0.6"
CornerRadius="8"
Padding="6"
SnapsToDevicePixels="True"
>
<Grid>
<!-- Items with children are
shown in an Expander. -->
<Expander Name="Exp" IsExpanded="{TemplateBinding TreeViewItem.IsExpanded}">
<Expander.Header>
<!-- Displays the item's header in the Expander. -->
<ContentPresenter ContentSource="Header" />
</Expander.Header>
<!-- Displays the item's children. -->
<ItemsPresenter />
</Expander>
<!-- Items without children are
shown in a ContentPresenter. -->
<ContentPresenter Name="CntPres"
ContentSource="Header"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Visibility="Collapsed"
/>
</Grid>
</Border>
</Grid>
<ControlTemplate.Triggers>
<!-- If the TreeViewItem has child items,
show it in an Expander. Otherwise
hide the Expander and show the hidden
ContentPresenter. -->
<Trigger Property="TreeViewItem.HasItems" Value="false">
<Setter
TargetName="Exp"
Property="Visibility"
Value="Collapsed" />
<Setter
TargetName="CntPres"
Property="Visibility"
Value="Visible" />
</Trigger>
<!--When the item is selected in the TreeView, use the
"selected" colors and give it a drop shadow. -->
<Trigger Property="IsSelected" Value="true">
<Setter
TargetName="Bd"
Property="Panel.Background"
Value="{StaticResource SelectedItemAreaBrush}" />
<Setter
TargetName="Bd"
Property="Border.BorderBrush"
Value="{StaticResource SelectedItemBorderBrush}" />
<!--<Setter
TargetName="Bd"
Property="TextElement.Foreground"
Value="{DynamicResource
{x:Static SystemColors.HighlightTextBrushKey}}" />-->
<Setter
TargetName="Bd"
Property="Border.BitmapEffect"
Value="{StaticResource DropShadowEffect}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<!-- Make each TreeViewItem show it's children
in a StackPanel. If it is a root item then
the Orientation will be 'Horizontal', else
'Vertical'. -->
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<ItemsPanelTemplate.Resources>
<this:ItemsPanelOrientationConverter x:Key="conv" />
</ItemsPanelTemplate.Resources>
<StackPanel
IsItemsHost="True"
Orientation="{Binding
RelativeSource={x:Static RelativeSource.TemplatedParent},
Converter={StaticResource conv}}"
/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
Does anybody know, what I am doing wrong in combining the style and functionality of my tree?
Is the problem that the style already defines something according to the isExpanded property? Or is there something missing, something along the lines of super(isExpanded)?
Thanks for your help!
Expander binding is probably the cause of the issue:
<Expander Name="Exp" IsExpanded="{TemplateBinding TreeViewItem.IsExpanded}">
according to documentation,
A TemplateBinding is always a one-way binding, even if properties involved default to two-way binding.
(see also TemplateBinding limitations)
try re-write binding as:
<Expander Name="Exp"
IsExpanded="{Binding IsExpanded,
RelativeSource={RelativeSource TemplatedParent}}">

How to draw expander (slider) in wpf

I have a requirement where I need a button which will let the user tap and swipe down/up in order to expand/collapse the control above the button. Something like in this image:
How can I achieve it in xaml?
You can create Template for Header and put an image from your question into HeaderTemplate. Let me show an example:
<Grid>
<Grid.Resources>
<Style TargetType="Border" x:Key="FooBorderStyle" >
<Style.Resources>
<LinearGradientBrush x:Key="ABackBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#EF3132" Offset="0.1" />
<GradientStop Color="#D62B2B" Offset="0.9" />
</LinearGradientBrush>
</Style.Resources>
<Setter Property="Background" Value="{StaticResource ABackBrush}"/>
</Style>
<DataTemplate x:Key="titleTemplate">
<Border Style="{StaticResource FooBorderStyle}" Height="24">
<Image Source="../Images/yourImage.png"
Margin="4 0"
VerticalAlignment="Center"/>
</Border>
</DataTemplate>
<Style TargetType="{x:Type Expander}">
<Setter Property="HeaderTemplate" Value="{StaticResource titleTemplate}"/>
</Style>
</Grid.Resources>
<Expander Name="hcontCtrl" Header="This is the header.">
<StackPanel>
<TextBox>This is a textbox</TextBox>
<Button>A button</Button>
</StackPanel>
</Expander>
</Grid>

Strange WPF DataGrid behavior: Little button like nubbies indenting some rows appearing to the left of the first column

I am binding the DataGrid to an ObservableCollection of custom objects. Intermittently I get (on maybe 2 or 3 rows) that a button like nubbie object (about maybe 4 pixels wide and the height of the row) appears on the left edge and causes the columns to indent slightly for that row so that they don't line up. I don't think there is anything special about those rows because if I rebind the grid to the same objects, the nubbies might not happen at all or might appear on different rows.
I am using some custom styling, and my first column is a DataTemplate, so I have included that below in case anyone can see anything in it that might be causing my issue. I'm kinda stumped at this point...
<DataGrid Style="{DynamicResource WPFDataGridStyle}" Background="White" BorderBrush="LightGray" FontSize="13"
CanUserReorderColumns="True" HorizontalGridLinesBrush="#FFEFEFEF" VerticalGridLinesBrush="#FFEFEFEF" HeadersVisibility="Column"
AlternatingRowBackground="#FFF4F4F4" CanUserResizeRows="False" SelectionMode="Single" AutoGenerateColumns="False"
CanUserAddRows="False" CanUserDeleteRows="False" CanUserSortColumns="True" FrozenColumnCount="3"
ItemsSource="{Binding VM.FilteredSteamJobs,Mode=TwoWay,Source={StaticResource VM}}"
SelectedItem="{Binding VM.SelectedJob,Mode=TwoWay,Source={StaticResource VM}}"
Visibility="{Binding VM.IsScheduleLoaded,Mode=OneWay,Source={StaticResource VM},Converter={StaticResource BoolToVisConv}}" >
<DataGrid.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#AAA7CDF0"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="#AAA7CDF0"/>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black"/>
<Style x:Key="WPFDataGridStyle" TargetType="{x:Type DataGrid}" BasedOn="{StaticResource {x:Type DataGrid}}">
<Setter Property="ColumnHeaderStyle" Value="{DynamicResource ColumnHeaderStyle1}"/>
<Setter Property="CellStyle" Value="{DynamicResource CellStyle1}"/>
</Style>
<Style x:Key="ColumnHeaderStyle1" TargetType="DataGridColumnHeader" BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
<Setter Property="Height" Value="25"/>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFC8E0FF" Offset="1"/>
<GradientStop Color="#FFF5FAFF" Offset="0"/>
<GradientStop Color="#FFDBEBFF" Offset="0.5"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Padding" Value="3"/>
<Setter Property="BorderThickness" Value="0.5,0"/>
<Setter Property="BorderBrush" Value="DarkGray"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="FontSize" Value="13" />
</Style>
<Style x:Key="CellStyle1" TargetType="{x:Type DataGridCell}">
<Setter Property="Height" Value="25"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Padding" Value="3,0"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<!--Selection Checkbox Column-->
<DataGridTemplateColumn IsReadOnly="True" CanUserResize="False" CanUserSort="False" Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<CheckBox VerticalAlignment="Center" HorizontalAlignment="Center" Margin="3"
IsChecked="{Binding Path=IsSelected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
Visibility="{Binding Status,Converter={StaticResource StatusToSelectVisConv}}">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.2" ScaleY="1.2"/>
</CheckBox.LayoutTransform>
</CheckBox>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox VerticalAlignment="Center" Checked="HeaderSelect_Checked" Unchecked="HeaderSelect_Unchecked">
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="1.3" ScaleY="1.3"/>
</CheckBox.LayoutTransform>
</CheckBox>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
</DataGridTemplateColumn>
I have been struggling with this issue as well, and if i'm not mistaking you have to set RowHeaderWidth="0" on the DataGrid to avoid this "bug".
Apparently the row headers are being shown for some random rows, even though HeadersVisibility is set to Column.

listbox design issue

i am trying to design some nice listbox, but every time i click on the item in the listbox
a selection background is ruined everything...
how can i make it irrelevant ?
this is the XAML:
<!-- Site List View -->
<ListBox Grid.Row="1" Name="SiteListBox" ItemsSource="{Binding}" HorizontalContentAlignment="Stretch">
<ListBox.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="Gainsboro" Offset="0.805" />
</LinearGradientBrush>
</ListBox.Background>
<ListBox.ItemContainerStyle>
<Style>
<Setter Property="Control.Padding" Value="0"></Setter>
<Style.Triggers>
<Trigger Property="ListBoxItem.IsSelected" Value="True">
<Setter Property="ListBoxItem.Background" Value="DarkRed" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Border Margin="5" BorderThickness="1" BorderBrush="SteelBlue" CornerRadius="4"
Background="{Binding Path=Background, RelativeSource={
RelativeSource
Mode=FindAncestor,
AncestorType={x:Type ListBoxItem}
}}">
<TextBlock Margin="5" Text="{Binding Path=Name}" />
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
a also attached a print screen.
You can change the default colors for when a ListBoxItem container IsSelected. Set them to Transparent to get the effect that you're after
<ListBox ...>
<ListBox.Resources>
<!-- Brush for selected item that doesn't have focus -->
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
<!-- Brush for selected item that has focus -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
</ListBox.Resources>
<!-- ... -->
</ListBox>

How do you style a WPF GridView Header?

I went from this: WPF GridViewHeader styling questions
to this:
Now I just need to get rid of the white space to the right of the "Size" header. I basically have a template for the GridViewColumnHeader that makes it a TextBlock. Is there any way I can set the background for that header area so that it spans the entire width of the GridView?
ADDED CODE:
This is my right-most column. The grid does not span 100% of available window area. In the header I need everything to the right of this column to have the same background as the column headers themselves.
<Style x:Key="GridHeaderRight" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
<TextBlock Text="{TemplateBinding Content}" Padding="5" Width="{TemplateBinding Width}" TextAlignment="Right">
<TextBlock.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0.0" Color="#373638" />
<GradientStop Offset="1.0" Color="#77797B" />
</LinearGradientBrush>
</TextBlock.Background>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Background" Value="Green" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0.0" Color="#373638" />
<GradientStop Offset="1.0" Color="#77797B" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
<GridViewColumn Width="200" HeaderContainerStyle="{ StaticResource GridHeaderRight}" Header="Size">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=EmployeeNumber}" HorizontalAlignment="Right"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
UPDATE
I am one step closer (I think) to solving this.
I added the following code inside the GridView tag:
<GridView.ColumnHeaderContainerStyle>
<Style TargetType="GridViewColumnHeader">
<Setter Property="BorderThickness" Value="1"></Setter>
<Setter Property="BorderBrush" Value="Green"></Setter>
<Setter Property="Height" Value="Auto"></Setter>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0.0" Color="#373638" />
<GradientStop Offset="1.0" Color="#77797B" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
</GridView.ColumnHeaderContainerStyle>
The border is there just so you can see the boundary of what this style covers. This is an enlarged image of what this does. It seems to be what I want if I can get rid of the little white border on the bottom.
So I guess removing that tiny white bottom border would also be an accepted answer for this one.
This is a simple style that will accomplish what you are looking for. Just change the Transparent background on the Border to be your desired gradient.
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
<Border BorderThickness="0,0,0,1" BorderBrush="Black" Background="Transparent">
<TextBlock x:Name="ContentHeader" Text="{TemplateBinding Content}" Padding="5,5,5,0" Width="{TemplateBinding Width}" TextAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontSize" Value="12" />
</Style>
sometimes the simplest way is the best. All you need to do it to change the TextBlock attached properties of GridViewColumnHeader
Define something like this in Resources:
<Style TargetType="{x:Type GridViewColumnHeader}" BasedOn="{StaticResource {x:Type GridViewColumnHeader}}">
<Setter Property="TextBlock.TextWrapping" Value="Wrap"/>
<Setter Property="TextBlock.Foreground" Value="Black"/>
</Style>
Have a look at the GridViewColumnHeader.Role property. The sample in the documentation for the GridViewColumnHeaderRole enumeration might give you some ideas...
EDIT: Have you considered using the GridView.HeaderStyle property ?
I solved this issue but I think there should be a better way of doing it. The problem was that I had TextBlocks on the header of each column. The unused area didn't have anything on the header row. I just added a TextBlock with the same background in the GridView.ColumnHeaderContainerStyle and it happened to span the rest of the unused width of the grid.
<GridView.ColumnHeaderContainerStyle>
<Style TargetType="GridViewColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
<TextBlock Text="" Padding="5">
<TextBlock.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0.0" Color="#373638" />
<GradientStop Offset="1.0" Color="#77797B" />
</LinearGradientBrush>
</TextBlock.Background>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GridView.ColumnHeaderContainerStyle>

Resources