WPF Listview Scrollbar Visibility Trigger - wpf

I'm trying to set up a trigger that removes the padding on the listview when the scrollbar is hidden.
I put the trigger on the listview style but I'm getting inconsistent results. For example the background property in the trigger is always active no matter what the scrollbar visibility is.
I've taken a look at the MSDN for the ScrollViewer.ComputedVerticalScrollBarVisibility Property but am not having much luck figuring out what's wrong.
<ListView Grid.Row="1" Grid.Column="1" BorderBrush="{x:Null}" BorderThickness="0" ItemsSource="{Binding Tasks}" Margin="5"
ScrollViewer.CanContentScroll="False" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<!-- SNIP -->
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Style>
<Style>
<Setter Property="ListView.Padding" Value="0,0,5,0"/>
<Setter Property="ListView.Background" Value="{x:Null}" />
<Style.Triggers>
<Trigger Property="ScrollViewer.ComputedVerticalScrollBarVisibility" Value="Hidden">
<Setter Property="ListView.Padding" Value="0"/>
<Setter Property="ListView.Background" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.Style>
</ListView>

I write an ListView style example which worked for me. I tried it.
<Style TargetType="ListView">
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListView">
<ScrollViewer>
<ScrollViewer.Style>
<Style TargetType="ScrollViewer">
<Style.Triggers>
<Trigger Property="ComputedVerticalScrollBarVisibility" Value="Visible">
<Setter Property="Padding" Value="100"/>
</Trigger>
<Trigger Property="ComputedVerticalScrollBarVisibility" Value="Collapsed">
<Setter Property="Padding" Value="10"/>
</Trigger>
</Style.Triggers>
</Style>
</ScrollViewer.Style>
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Related

Creating a style based on another which is using a data template

I have a style for a ListBox using TextBoxes as defined below:
<Style x:Key="MyListBoxStyle" TargetType="ListBox">
<Setter Property="Background" Value="LightGray"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Text="{Binding Mode=OneWay}" Background="LightGray"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
I use this style for a number of ListBox display readonly data.
What I also have is a group of ListBoxes in which I would like to be able to click on one of the TextBoxes in them and then perform some action. So what I want to do is attach a Click event on the TextBox. Ideally I'd like to leverage the above style without having to retype it all and just add a new style which added the event binding. How would yo go about this?
Style.BaseOn
<Style x:Key="MyListBoxStyle" TargetType="ListBox">
<Setter Property="Background" Value="LightGray"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Text="{Binding Mode=OneWay}" Background="LightGray"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="MyListBoxStyle2" BasedOn="{StaticResource MyListBoxStyle}" TargetType="ListBox">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Text="{Binding Mode=OneWay}" Background="LightGray" GotFocus="TextBox_GotFocus"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>

ListView without hover and selected style but with alternating listviewitem color style

I try to create a ListView which doesn't have a hover and selected style but has alternating colors for the ListViewItem's.
To disable the styles I set the ItemContainerStyle. The problem is that the expression ListView.AlternationIndex is somehow allways evaluating to 0 as Christian Mosers WPF Inspector tells me. This results in that the background color for all items is red.
<ListView ItemsSource="{Binding Configuration}" AlternationCount="2" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border>
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<Trigger Property="ListView.AlternationIndex" Value="0">
<Setter Property="Background" Value="Red" />
</Trigger>
<Trigger Property="ListView.AlternationIndex" Value="1">
<Setter Property="Background" Value="Blue" />
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
How can I color the items alternating wihout having the selected and hover style?
(The background color of the first item should be red the one of the second blue the one of the third red again and so on)
(The Backgroundcolor, border, padding, margin and so on should not change when the mouse is over an ListViewItem or a ListViewItem is selected)
EDIT: Thanks for the answers. I changed added a template binding to the solution to get rid of the Name property.
<ListView ItemsSource="{Binding Configuration}" AlternationCount="2" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="ListBox.AlternationIndex" Value="0">
<Setter Property="Border.Background" Value="Red" />
</Trigger>
<Trigger Property="ListBox.AlternationIndex" Value="1">
<Setter Property="Border.Background" Value="Blue" />
</Trigger>
</Style.Triggers>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border Background="{TemplateBinding Background}">
<ContentPresenter Content="{TemplateBinding Content}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
Put the triggers in <ControlTemplate.Triggers>:
<ListView ItemsSource="{Binding Configuration}" AlternationCount="2" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border x:Name="Border">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="Red" TargetName="Border" />
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="Blue" TargetName="Border" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
The triggers have to be on the control template; the Border doesn't know anything about its parent.
But since the property to set (Background) is on the Border, you have to name it and use TargetName.
<ListView AlternationCount="2" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border Name="border">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" TargetName="border" Value="Red" />
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" TargetName="border" Value="Blue" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListViewItem Content="ABC"/>
<ListViewItem Content="DEF"/>
<ListViewItem Content="GHI"/>
<ListViewItem Content="JKL"/>
</ListView>
This XAML produces the desired result:

How to set a border around listviewitem in WPF

My ListView should have following style:
no border around the whole ListView (achieved)
no highlighting when interacting with ListViewItem (achieved)
border around selected ListViewItem (missing)
My ListView:
<ListView DisplayMemberPath="Name" BorderThickness="0" >
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<!-- get rid of the highlighting -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
<!-- style selected item -->
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontSize" Value="20" />
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>
I tried this and this, both doesn't work for me. I guess my problem is the template but I have no idea how to put a border around the selected ListViewItem.
Update
Working solution:
<ListView DisplayMemberPath="Name" BorderThickness="0" >
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<!-- get rid of the highlighting -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border x:Name="Border">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontSize" Value="20" />
<Setter Property="FontWeight" Value="Bold" />
<Setter TargetName="Border" Property="BorderBrush" Value="Black"/>
<Setter TargetName="Border" Property="BorderThickness" Value="2"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
Maybe this works. Add a Border around ContentPresenter an use controlTemplate Triggers
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border x:Name="Border">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontSize" Value="20" />
<Setter Property="FontWeight" Value="Bold" />
<Setter TargetName="Border" Property="BorderBrush" Value="Red"/>
<Setter TargetName="Border" Property="BorderThickness" Value="1"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>

WPF- trigger target not found

I have own style on listbox, I use in style data template and also control template.
In data template I create listbox item with some textboxes. In control template I want create a trigger which change foreground color of some textbox if listbox item is selected.
Here is some from style:
<Style x:Key="lbStyle" TargetType="{x:Type ListBox}">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Grid Name="MainGrid">
<TextBlock Name="tbName" Text="{Binding Value.nick}"
Grid.Column="0" Grid.Row="0" Margin="2,2,2,2"
FontSize="13" FontWeight="Medium"></TextBlock>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="tbName" Property="Foreground" Value="Black"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Problem is, I get compile error : Cannot find the Trigger target tbName.
<Style TargetType="ListBox">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding}" Margin="2" FontSize="13" FontWeight="Medium">
<TextBlock.Style>
<Style BasedOn="{StaticResource {x:Type TextBlock}}" TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListBoxItem}, Path=IsSelected}" Value="True">
<Setter Property="Foreground" Value="Black"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
Your code of template is incorrect. You apply ListBoxItem template to ListBox template. Also, you didn't add anything inside ControlTemplate.
I have rewrited it:
<Style x:Key="itemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter x:Name="itemContent"/>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="itemContent" Property="TextBlock.Foreground" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
ListBox with applied style:
<ListBox ItemContainerStyle="{StaticResource itemStyle}" />

Styling TabItem when populated with ItemsSource

I'm using a WPF Tabcontrol populated with a collection using Itemssource.
<TabControl x:Name="_tabControl" ItemsSource="{Binding TabViewModelList}">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Header" Value="{Binding TabCaption}"/>
<Setter Property="Content" Value="{Binding TabContent}"/>
<Setter Property="IsSelected" Value="{Binding IsDefault}"/>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
Now I want to set my TabItem-style in my App.xaml(or other resourcefile) like this:
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border
Name="Border"
Background="LightBlue"
BorderBrush="Black"
BorderThickness="1,1,1,1"
CornerRadius="6,6,0,0" >
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="12,2,12,2"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="LightBlue" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="LightGray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
..but the ItemContainerStyle, of course overrides the controltemplate.
How do I combine these two so I can load my tabcontrol dynamically and still be able to style my TabItems the way I want to?
Ok... Solved my own problem. Pretty obvious..
Named my template
<Style TargetType="{x:Type TabItem}" x:Key="TabItemTemplate">
Added a BasedOn property like this:
<Style TargetType="TabItem" BasedOn="{StaticResource TabItemTemplate}">
But if I could combine them into one template please let me know...

Resources