I've finally managed to get my layout right and animation working and it's not smooth. It has a huge jitter/step right in the middle.
I have a ListBox using a StackPanel ItemsPanel, the ListBoxItems are styled using a DataTemplate. The items are images with a reflection using borders and visual brushes.
<UserControl x:Class="Thumbnails"
xmlns:local="clr-namespace:ContentPresenter"
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:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="350" d:DesignWidth="800">
<UserControl.Resources>
<local:ThumbImageHeightConverter x:Key="HeightConv" />
<local:ThumbImageWidthConverter x:Key="WidthConv" />
<local:InnerGridHeightConverter x:Key="InnerGridHeightConv" />
<local:ReflectWidthConverter x:Key="ReflectWidthConv" />
<local:ReflectCenterYConv x:Key="ReflectCenterYConv" />
<local:BorderThicknessScale x:Key="BorderThicknessScale" />
<local:BorderCornerRadiusScale x:Key="BorderCornerRadiusScale" />
<Storyboard x:Key="FadeUpAndFlash">
<!--<DoubleAnimation From="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Duration="0:0:10" FillBehavior="Stop" />-->
<DoubleAnimation From="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Duration="0:0:1" FillBehavior="Stop" />
</Storyboard>
<Storyboard x:Key="ReflectFadeUpAndFlash">
<!--<DoubleAnimation From="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Duration="0:0:10" FillBehavior="Stop" />-->
<DoubleAnimation From="0" To="0.75" Storyboard.TargetProperty="(UIElement.Opacity)" Duration="0:0:1" FillBehavior="Stop" />
</Storyboard>
<Style TargetType="{x:Type ListBox}">
<!-- Set the ItemTemplate of the ListBox to a DataTemplate which explains how to display an object of type BitmapImage. -->
<Style.Resources>
<!-- Background of selected item when focussed -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Black"/>
<!-- Background of selected item when not focussed -->
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Black" />
</Style.Resources>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Grid x:Name="ThumbGrid" VerticalAlignment="Top" Height="{Binding ElementName=ThumbListBox, Path=ActualHeight}" >
<Grid.RowDefinitions>
<RowDefinition x:Name="ThumbGridThumbImgRow" Height="80*" ></RowDefinition>
<RowDefinition x:Name="GridReflectRow" Height="20*" ></RowDefinition>
</Grid.RowDefinitions>
<Border x:Name="HighlightBorder" Padding="2" Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderBrush" Value="Black"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True">
<DataTrigger.Setters>
<Setter Property="BorderBrush" Value="Yellow"/>
</DataTrigger.Setters>
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource FadeUpAndFlash}" Name="AnimateImageBorder" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="AnimateImageBorder" />
</DataTrigger.ExitActions>
<!--<Setter Property="BorderBrush" Value="Yellow"/>-->
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Border.Resources>
<sys:Int32 x:Key="HighlightBorderOrigRadius">18</sys:Int32>
</Border.Resources>
<Border.CornerRadius>
<MultiBinding Converter="{StaticResource BorderCornerRadiusScale}">
<Binding ElementName="HighlightBorder" Path="ActualWidth" />
<Binding Source="{StaticResource HighlightBorderOrigRadius}" />
</MultiBinding>
</Border.CornerRadius>
<Border.BorderThickness>
<MultiBinding Converter="{StaticResource BorderThicknessScale}">
<Binding ElementName="HighlightBorder" Path="ActualWidth" />
</MultiBinding>
</Border.BorderThickness>
<Grid x:Name="ThumbInnerGrid">
<Grid.Height>
<MultiBinding Converter="{StaticResource InnerGridHeightConv}">
<Binding ElementName="ThumbGrid" Path="ActualHeight" />
<Binding ElementName="HighlightBorder" Path="CornerRadius" />
<Binding ElementName="mask" Path="CornerRadius" />
</MultiBinding>
</Grid.Height>
<Border x:Name="mask" Background="Black">
<Border.Resources>
<sys:Int32 x:Key="MaskBorderOrigRadius">15</sys:Int32>
</Border.Resources>
<Border.CornerRadius>
<MultiBinding Converter="{StaticResource BorderCornerRadiusScale}">
<Binding ElementName="mask" Path="ActualWidth" />
<Binding Source="{StaticResource MaskBorderOrigRadius}" />
</MultiBinding>
</Border.CornerRadius>
</Border>
<StackPanel x:Name="ThumbInnerStack" VerticalAlignment="Top">
<StackPanel.OpacityMask>
<VisualBrush Visual="{Binding ElementName=mask}"/>
</StackPanel.OpacityMask>
<Image x:Name="ThumbImg" Stretch="UniformToFill" SnapsToDevicePixels="True" >
<Image.Height>
<MultiBinding Converter="{StaticResource HeightConv}">
<Binding ElementName="HighlightBorder" Path="ActualHeight" />
<Binding ElementName="HighlightBorder" Path="BorderThickness" />
<Binding ElementName="HighlightBorder" Path="Padding" />
</MultiBinding>
</Image.Height>
<Image.Width>
<MultiBinding Converter="{StaticResource WidthConv}">
<Binding ElementName="ThumbImg" Path="ActualHeight" />
<Binding ElementName="HighlightBorder" Path="BorderThickness" />
<Binding ElementName="HighlightBorder" Path="Padding" />
</MultiBinding>
</Image.Width>
<Image.Source>
<BitmapImage UriSource="{Binding Path=Src}"></BitmapImage>
</Image.Source>
</Image>
</StackPanel>
</Grid>
</Border>
<Border x:Name="ReflectBorder" Margin="0,-1,0,0" VerticalAlignment="Top" Height="{Binding ElementName=ThumbImg, Path=ActualHeight}" Grid.Row="1" SnapsToDevicePixels="True" Opacity="0.75" >
<Border.Style>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource ReflectFadeUpAndFlash}" Name="AnimateImageReflection" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="AnimateImageReflection" />
</DataTrigger.ExitActions>
<!--<Setter Property="BorderBrush" Value="Yellow"/>-->
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Border.Resources>
<sys:Int32 x:Key="MaskBorderOrigRadius">15</sys:Int32>
</Border.Resources>
<Border.CornerRadius>
<MultiBinding Converter="{StaticResource BorderCornerRadiusScale}">
<Binding ElementName="ReflectBorder" Path="ActualWidth" />
<Binding Source="{StaticResource MaskBorderOrigRadius}" />
</MultiBinding>
</Border.CornerRadius>
<Border.Width>
<MultiBinding Converter="{StaticResource ReflectWidthConv}">
<Binding ElementName="HighlightBorder" Path="ActualWidth" />
<Binding ElementName="HighlightBorder" Path="BorderThickness" />
</MultiBinding>
</Border.Width>
<Border.Background>
<VisualBrush Visual="{Binding ElementName=ThumbImg}">
<VisualBrush.Transform>
<ScaleTransform ScaleX="1" ScaleY="-1" CenterX="200">
<ScaleTransform.CenterY>
<MultiBinding Converter="{StaticResource ReflectCenterYConv}">
<Binding ElementName="ThumbImg" Path="ActualHeight" />
</MultiBinding>
</ScaleTransform.CenterY>
</ScaleTransform>
</VisualBrush.Transform>
</VisualBrush>
</Border.Background>
<Border.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1.3">
<GradientStop Offset="0" Color="Black"></GradientStop>
<GradientStop Offset="0.15" Color="Transparent"></GradientStop>
</LinearGradientBrush>
</Border.OpacityMask>
</Border>
<Grid Grid.Row="1" MaxWidth="{Binding ElementName=ThumbImg, Path=ActualWidth}">
<Border Padding="10,0,10,25">
<Viewbox VerticalAlignment="Top" MaxWidth="{Binding ElementName=ThumbImg, Path=ActualWidth}">
<Label x:Name="ThumbTitle" Margin="0,-5,0,0" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Top" Content="{Binding Path=Title}" FontFamily="Arial" Foreground="White" />
</Viewbox>
</Border>
</Grid>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel x:Name="ThumbListStack" Orientation="Horizontal" Loaded="StackPanel_Loaded">
<StackPanel.RenderTransform>
<TranslateTransform X="0" Y="0" />
</StackPanel.RenderTransform>
</StackPanel>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled" />
<Setter Property="Background" Value="Black"/>
</Style>
</UserControl.Resources>
<UserControl.DataContext>
<ObjectDataProvider ObjectType="{x:Type local:ThumbImageLoader}" MethodName="LoadImagesv2" IsAsynchronous="True" />
</UserControl.DataContext>
<!-- This ListBox is the Content of the Window. Normally you would have a panel of some type as the Window's Content, but let's keep it simple. -->
<Grid x:Name="ThumbListBoxGrid">
<ListBox x:Name="ThumbListBox" ItemsSource="{Binding}" VerticalAlignment="Top" Height="{Binding ElementName=ThumbListBoxGrid, Path=ActualHeight}" IsSynchronizedWithCurrentItem="True" />
</Grid>
Here is the code-behind that controls the TranslateTransform animation:
RenderTransform = New TranslateTransform()
Dim d As New Duration(New TimeSpan(0, 0, 0, 1, 30))
Dim x As New DoubleAnimation(translatePosition.X, d)
x.EasingFunction = New PowerEase() With {.EasingMode = EasingMode.EaseInOut, .Power = 4}
Storyboard.SetTarget(x, m_itemsPanelStackPanel)
Storyboard.SetTargetProperty(x, New PropertyPath("(StackPanel.RenderTransform).(TranslateTransform.X)"))
Timeline.SetDesiredFrameRate(x, 120)
'Storyboard.SetDesiredFrameRate(x, 120) 'have tried setting the FrameRate both ways
Dim sb As New Storyboard()
sb.Children.Add(x)
sb.Begin()
I have tried disabling the Ease but no improvement.
Are there known problems with TranslateTransform?
Is there anything else I can do to improve performance? Is there a better way to animate the x axis to get the images in the listbox to scroll horizontally?
Related
I have a Popover control whose IsOpen is set to true under 2 conditions (When a string property has value and IsMouse over on the Ui Control is true). The Popover should open after a delay of 0.3 seconds .
Sample
<ContentControl Content="{Binding}"
Background="Transparent"
AutomationProperties.AutomationId="xyz.ssd">
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="FontSize" Value="15" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Border x:Name="ertt">
<StackPanel x:Name="Grid1" MouseEnter="Image11_OnMouseEnter"
MouseLeave="Image11_OnMouseLeave" MouseDown="Grid1_OnMouseDown">
<Image Height="60" Width="60" Source="{StaticResource SampleImage}"
ToolTip="{Binding DataContext.SomeTextToDisplay , RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=tlui:MainWindow} , Mode=TwoWay}"
DocumentViewerBase.IsMasterPage="True"
x:Name="Image11" >
</Image>
<controls:Popover
PlacementTarget="{Binding ElementName=Image11}"
Placement="Bottom" Height="1" Width="1"
FocusManager.IsFocusScope="False"
controls:DialogWindowCloseBehavior.IsCloseButton="False"
AllowDrop="False"
AutomationProperties.IsOffscreenBehavior="FromClip"
controls:BackgroundBlurBehavior.BackgroundBlur="True"
controls:CultureBehavior.UseHarmonizedCulture="False"
ArrowHeight="1"
StaysOpen="True"
x:Name="SomePopover"
>
<!--<controls:Popover.IsOpen>
<MultiBinding Converter="{StaticResource BooleanToVisibilityConverter}">
<Binding Path="DataContext.SomeTextToDisplay"
RelativeSource="{RelativeSource Mode=FindAncestor,
AncestorType=tlui:MainWindow}" />
<Binding Path="IsPopOverOpen" RelativeSource="{RelativeSource AncestorType=conv:UserControl1}"
/>
</MultiBinding>
</controls:Popover.IsOpen>-->
<controls:Popover.IsHitTestVisible>False</controls:Popover.IsHitTestVisible>
<controls:Popover.IsManipulationEnabled>False</controls:Popover.IsManipulationEnabled>
<controls:Popover.VerticalOffset>-1</controls:Popover.VerticalOffset>
<Border Margin="10,0,0,0" ClipToBounds="True">
<Border.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="Width" Value="60" />
<Setter Property="Height" Value="60" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</Border.Resources>
<StackPanel>
<TextBlock x:Name="NotesComment"
TextWrapping="Wrap">
<TextBlock.Text>
<Binding Path="DataContext.SomeTextToDisplay"
RelativeSource="{RelativeSource Mode=FindAncestor,
AncestorType=tlui:MainWindow}" />
</TextBlock.Text>
</TextBlock>
</StackPanel>
</Border>
</controls:Popover>
</StackPanel>
</Border>
<DataTemplate.Resources>
<Storyboard x:Key="OpenPopOver">
<BooleanAnimationUsingKeyFrames
Storyboard.TargetName="SomePopover"
Storyboard.TargetProperty="IsOpen"
FillBehavior="Stop">
<DiscreteBooleanKeyFrame KeyTime="0:0:2.3" Value="False"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</DataTemplate.Resources>
<DataTemplate.Triggers>
<Trigger SourceName="ertt" Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard x:Name="bsb" >
<Storyboard>
<BooleanAnimationUsingKeyFrames
Storyboard.TargetName="SomePopover"
Storyboard.TargetProperty="IsOpen"
FillBehavior="HoldEnd">
<DiscreteBooleanKeyFrame KeyTime="0:0:1.3"
Value="{Binding ElementName=Image11 ,Path=ToolTip,
Converter={x:Static converter:StringtoBool.Instance}}"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="bsb"/>
<BeginStoryboard x:Name="bxb" Storyboard="{StaticResource OpenPopOver}"/>
</Trigger.ExitActions>
</Trigger>
<Trigger SourceName="SomePopover" Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<StopStoryboard BeginStoryboardName="bsb"/>
</Trigger.EnterActions>
<!--<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource OpenPopOver}"/>
<RemoveStoryboard BeginStoryboardName="bxb"/>
</Trigger.ExitActions>-->
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ContentControl.Style>
</ContentControl>
Problem is whenever I am hovering on the contentcontrol the popover is getting displayed. It should Only display when Both IsMouseOver on ContentControl is tru AND The image(Image11) has a tooltip that shows the description . The Image is not visible in certain scenarios.In those scenarios the Popover should not Open while hovering on contentcontrol
I have created a style for my custom Control (ButtonAnalysisControl). Everything is working except the ToolTip. When I move the mouse over a MenuItem the ToolTip doesn't show up. I inspected the MenuItems with Snoopand the ToolTip value is correctly set. How can I make the ToolTip work? Bonus question: How can I remove the Border in my ContextMenu?
ContextMenu:
Generic.xaml Style
<Style TargetType="anal:ButtonAnalysisControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="anal:ButtonAnalysisControl">
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Click">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="ContextMenu" Storyboard.TargetProperty="(ContextMenu.IsOpen)">
<DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
<ControlTemplate.Resources>
<anal:CustomMultiValueConvertor x:Key="CustomMultiValueConvertor"/>
<anal:IntToPercentageBrushConvertor x:Key="IntToPercentageBrushConvertor"/>
</ControlTemplate.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.ContextMenu>
<ContextMenu Name="ContextMenu" IsOpen="False" Placement="Top" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">
<ContextMenu.ItemsSource>
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="ChildCommands"/>
</ContextMenu.ItemsSource>
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="MenuItem.Header">
<Setter.Value>
<MultiBinding Converter="{StaticResource CustomMultiValueConvertor}">
<Binding Path="Percentage" />
<Binding Path="ViewCommand.Command.Text" />
</MultiBinding>
</Setter.Value>
</Setter>
<Setter Property="MenuItem.IsEnabled" Value="False"/>
<Setter Property="MenuItem.Background" Value="{Binding Percentage, Converter={StaticResource IntToPercentageBrushConvertor}}"/>
<Setter Property="MenuItem.Padding" Value="0"/>
<Setter Property="MenuItem.BorderThickness" Value="0"/>
<Setter Property="MenuItem.ToolTip" Value="123"/>
</Style>
</ContextMenu.ItemContainerStyle>
<ContextMenu.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ContextMenu.ItemsPanel>
</ContextMenu>
</Grid.ContextMenu>
<TextBlock TextAlignment="Center"
VerticalAlignment="Stretch"
Foreground="{StaticResource CommandBarForeground}"
Background="{StaticResource MainForegroundBrush}"
FontFamily="{StaticResource FontFamily}"
FontSize="10"
Grid.Column="0"
Grid.Row="0">
<TextBlock.Text>
<Binding Path="Text" StringFormat="{}{0}%" RelativeSource="{RelativeSource TemplatedParent}" />
</TextBlock.Text>
</TextBlock>
<Rectangle Grid.Column="0"
Grid.Row="1">
<Rectangle.Fill>
<Binding Path="BackgroundBrush" RelativeSource="{RelativeSource TemplatedParent}" />
</Rectangle.Fill>
</Rectangle>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I found the answer: the ToolTip didn't show up because the MenuItem is disabled.
Adding this line to my MenuItem style fixed it:
<Setter Property="ToolTipService.ShowOnDisabled" Value="True" />
I've got this user control which is producing a 1px border around the ListBox.
I've found out it's the default Bd Border. I just can't seem to work out how to style it so the 1px gap no longer appears.
<UserControl x:Class="Thumbnails"
xmlns:local="clr-namespace:ContentPresenter"
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:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="350" d:DesignWidth="800">
<UserControl.Resources>
<local:ThumbImageHeightConverter x:Key="HeightConv" />
<local:ThumbImageWidthConverter x:Key="WidthConv" />
<local:InnerGridHeightConverter x:Key="InnerGridHeightConv" />
<local:ReflectWidthConverter x:Key="ReflectWidthConv" />
<local:ReflectCenterYConv x:Key="ReflectCenterYConv" />
<local:BorderThicknessScale x:Key="BorderThicknessScale" />
<local:BorderCornerRadiusScale x:Key="BorderCornerRadiusScale" />
<Storyboard x:Key="FadeUpAndFlash">
<!--<DoubleAnimation From="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Duration="0:0:10" FillBehavior="Stop" />-->
<DoubleAnimation From="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Duration="0:0:1" FillBehavior="Stop" />
</Storyboard>
<Storyboard x:Key="ReflectFadeUpAndFlash">
<!--<DoubleAnimation From="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Duration="0:0:10" FillBehavior="Stop" />-->
<DoubleAnimation From="0" To="0.75" Storyboard.TargetProperty="(UIElement.Opacity)" Duration="0:0:1" FillBehavior="Stop" />
</Storyboard>
<Style TargetType="{x:Type ListBox}">
<!-- Set the ItemTemplate of the ListBox to a DataTemplate which explains how to display an object of type BitmapImage. -->
<Style.Resources>
<!-- Background of selected item when focussed -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Black"/>
<!-- Background of selected item when not focussed -->
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Black" />
</Style.Resources>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Grid x:Name="ThumbGrid" VerticalAlignment="Top" Height="{Binding ElementName=ThumbListBox, Path=ActualHeight}" >
<Grid.RowDefinitions>
<RowDefinition x:Name="ThumbGridThumbImgRow" Height="80*" ></RowDefinition>
<RowDefinition x:Name="GridReflectRow" Height="20*" ></RowDefinition>
</Grid.RowDefinitions>
<Border x:Name="HighlightBorder" Padding="2" Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderBrush" Value="Black"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True">
<DataTrigger.Setters>
<Setter Property="BorderBrush" Value="Yellow"/>
</DataTrigger.Setters>
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource FadeUpAndFlash}" Name="AnimateImageBorder" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="AnimateImageBorder" />
</DataTrigger.ExitActions>
<!--<Setter Property="BorderBrush" Value="Yellow"/>-->
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Border.Resources>
<sys:Int32 x:Key="HighlightBorderOrigRadius">18</sys:Int32>
</Border.Resources>
<Border.CornerRadius>
<MultiBinding Converter="{StaticResource BorderCornerRadiusScale}">
<Binding ElementName="HighlightBorder" Path="ActualWidth" />
<Binding Source="{StaticResource HighlightBorderOrigRadius}" />
</MultiBinding>
</Border.CornerRadius>
<Border.BorderThickness>
<MultiBinding Converter="{StaticResource BorderThicknessScale}">
<Binding ElementName="HighlightBorder" Path="ActualWidth" />
</MultiBinding>
</Border.BorderThickness>
<Grid x:Name="ThumbInnerGrid">
<Grid.Height>
<MultiBinding Converter="{StaticResource InnerGridHeightConv}">
<Binding ElementName="ThumbGrid" Path="ActualHeight" />
<Binding ElementName="HighlightBorder" Path="CornerRadius" />
<Binding ElementName="mask" Path="CornerRadius" />
</MultiBinding>
</Grid.Height>
<Border x:Name="mask" Background="Black">
<Border.Resources>
<sys:Int32 x:Key="MaskBorderOrigRadius">15</sys:Int32>
</Border.Resources>
<Border.CornerRadius>
<MultiBinding Converter="{StaticResource BorderCornerRadiusScale}">
<Binding ElementName="mask" Path="ActualWidth" />
<Binding Source="{StaticResource MaskBorderOrigRadius}" />
</MultiBinding>
</Border.CornerRadius>
</Border>
<StackPanel x:Name="ThumbInnerStack" VerticalAlignment="Top">
<StackPanel.OpacityMask>
<VisualBrush Visual="{Binding ElementName=mask}"/>
</StackPanel.OpacityMask>
<Image x:Name="ThumbImg" Stretch="UniformToFill" >
<Image.Height>
<MultiBinding Converter="{StaticResource HeightConv}">
<Binding ElementName="HighlightBorder" Path="ActualHeight" />
<Binding ElementName="HighlightBorder" Path="BorderThickness" />
<Binding ElementName="HighlightBorder" Path="Padding" />
</MultiBinding>
</Image.Height>
<Image.Width>
<MultiBinding Converter="{StaticResource WidthConv}">
<Binding ElementName="ThumbImg" Path="ActualHeight" />
<Binding ElementName="HighlightBorder" Path="BorderThickness" />
<Binding ElementName="HighlightBorder" Path="Padding" />
</MultiBinding>
</Image.Width>
<Image.Source>
<BitmapImage UriSource="{Binding Path=Src}"></BitmapImage>
</Image.Source>
</Image>
</StackPanel>
</Grid>
</Border>
<Border x:Name="ReflectBorder" Margin="0,-1,0,0" VerticalAlignment="Top" Height="{Binding ElementName=ThumbImg, Path=ActualHeight}" Grid.Row="1" Opacity="0.75" >
<Border.Style>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource ReflectFadeUpAndFlash}" Name="AnimateImageReflection" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="AnimateImageReflection" />
</DataTrigger.ExitActions>
<!--<Setter Property="BorderBrush" Value="Yellow"/>-->
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Border.Resources>
<sys:Int32 x:Key="MaskBorderOrigRadius">15</sys:Int32>
</Border.Resources>
<Border.CornerRadius>
<MultiBinding Converter="{StaticResource BorderCornerRadiusScale}">
<Binding ElementName="ReflectBorder" Path="ActualWidth" />
<Binding Source="{StaticResource MaskBorderOrigRadius}" />
</MultiBinding>
</Border.CornerRadius>
<Border.Width>
<MultiBinding Converter="{StaticResource ReflectWidthConv}">
<Binding ElementName="HighlightBorder" Path="ActualWidth" />
<Binding ElementName="HighlightBorder" Path="BorderThickness" />
</MultiBinding>
</Border.Width>
<Border.Background>
<VisualBrush Visual="{Binding ElementName=ThumbImg}">
<VisualBrush.Transform>
<ScaleTransform ScaleX="1" ScaleY="-1" CenterX="200">
<ScaleTransform.CenterY>
<MultiBinding Converter="{StaticResource ReflectCenterYConv}">
<Binding ElementName="ThumbImg" Path="ActualHeight" />
</MultiBinding>
</ScaleTransform.CenterY>
</ScaleTransform>
</VisualBrush.Transform>
</VisualBrush>
</Border.Background>
<Border.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1.3">
<GradientStop Offset="0" Color="Black"></GradientStop>
<GradientStop Offset="0.15" Color="Transparent"></GradientStop>
</LinearGradientBrush>
</Border.OpacityMask>
</Border>
<Grid Grid.Row="1" MaxWidth="{Binding ElementName=ThumbImg, Path=ActualWidth}">
<Border Padding="10,0,10,25">
<Viewbox VerticalAlignment="Top" MaxWidth="{Binding ElementName=ThumbImg, Path=ActualWidth}">
<Label x:Name="ThumbTitle" Margin="0,-5,0,0" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Top" Content="{Binding Path=Title}" FontFamily="Arial" Foreground="White" />
</Viewbox>
</Border>
</Grid>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel x:Name="ThumbListStack" Orientation="Horizontal" Loaded="StackPanel_Loaded">
<VirtualizingStackPanel.RenderTransform>
<TranslateTransform X="0" Y="0" />
</VirtualizingStackPanel.RenderTransform>
</VirtualizingStackPanel>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled" />
<Setter Property="Background" Value="Black"/>
</Style>
</UserControl.Resources>
<UserControl.DataContext>
<ObjectDataProvider ObjectType="{x:Type local:ThumbImageLoader}" MethodName="LoadImagesv2" IsAsynchronous="True" />
</UserControl.DataContext>
<!-- This ListBox is the Content of the Window. Normally you would have a panel of some type as the Window's Content, but let's keep it simple. -->
<Grid x:Name="ThumbListBoxGrid">
<ListBox x:Name="ThumbListBox" ItemsSource="{Binding}" VerticalAlignment="Top" Height="{Binding ElementName=ThumbListBoxGrid, Path=ActualHeight}" IsSynchronizedWithCurrentItem="True" />
</Grid>
How do I style the default Border?
Here is what I used.
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border BorderBrush="{TemplateBinding Border.BorderBrush}" BorderThickness="0" Name="Bd" Background="{TemplateBinding Panel.Background}" SnapsToDevicePixels="True" Padding="0">
<ScrollViewer Focusable="False" Padding="{TemplateBinding Control.Padding}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
I'm trying to change the background of the selected item in a WPF ListBox.
I have attempted to implement a style for it, but for some reason it's not being applied. I still get a blue background. Can anyone see why?
<UserControl x:Class="Thumbnails"
xmlns:local="clr-namespace:ContentPresenter"
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"
mc:Ignorable="d"
d:DesignHeight="350" d:DesignWidth="800">
<UserControl.Resources>
<local:ThumbImageHeightConverter x:Key="HeightConv" />
<local:ThumbImageWidthConverter x:Key="WidthConv" />
<local:InnerGridHeightConverter x:Key="InnerGridHeightConv" />
<local:ReflectWidthConverter x:Key="ReflectWidthConv" />
<local:ReflectCenterYConv x:Key="ReflectCenterYConv" />
<Style x:Name="ListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<Trigger Property="Selector.IsSelected" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type ListBox}">
<!-- Set the ItemTemplate of the ListBox to a DataTemplate which explains how to display an object of type BitmapImage. -->
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Grid x:Name="ThumbGrid" VerticalAlignment="Top" Height="{Binding ElementName=ThumbListBox, Path=ActualHeight}" >
<Grid.RowDefinitions>
<RowDefinition x:Name="ThumbGridThumbImgRow" ></RowDefinition>
<RowDefinition x:Name="GridReflectRow" Height="40" ></RowDefinition>
</Grid.RowDefinitions>
<Border x:Name="HighlightBorder" BorderThickness="7" BorderBrush="Black" CornerRadius="18" Padding="2" Margin="4" HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid x:Name="ThumbInnerGrid">
<Grid.Height>
<MultiBinding Converter="{StaticResource InnerGridHeightConv}">
<Binding ElementName="ThumbGrid" Path="ActualHeight" />
<Binding ElementName="HighlightBorder" Path="CornerRadius" />
<Binding ElementName="mask" Path="CornerRadius" />
</MultiBinding>
</Grid.Height>
<Border x:Name="mask" Background="White" CornerRadius="15" />
<StackPanel x:Name="ThumbInnerStack" >
<StackPanel.OpacityMask>
<VisualBrush Visual="{Binding ElementName=mask}"/>
</StackPanel.OpacityMask>
<!--<Image x:Name="ThumbImg" Source="{Binding Path=UriSource}" Stretch="Fill" Width="{Binding}" Height="{Binding Source={StaticResource ThumbImageSize}, Path=ImgHeight}">-->
<Image x:Name="ThumbImg" Stretch="UniformToFill" SnapsToDevicePixels="True" >
<Image.Height>
<MultiBinding Converter="{StaticResource HeightConv}">
<Binding ElementName="HighlightBorder" Path="ActualHeight" />
<Binding ElementName="HighlightBorder" Path="BorderThickness" />
<Binding ElementName="HighlightBorder" Path="Padding" />
</MultiBinding>
</Image.Height>
<Image.Width>
<MultiBinding Converter="{StaticResource WidthConv}">
<Binding ElementName="ThumbImg" Path="ActualHeight" />
<Binding ElementName="HighlightBorder" Path="BorderThickness" />
<Binding ElementName="HighlightBorder" Path="Padding" />
</MultiBinding>
</Image.Width>
<Image.Source>
<BitmapImage UriSource="{Binding Path=Src}"></BitmapImage>
</Image.Source>
</Image>
</StackPanel>
</Grid>
</Border>
<Border Height="{Binding ElementName=ThumbImg, Path=ActualHeight}" Grid.Row="1" CornerRadius="15" SnapsToDevicePixels="True" Opacity="0.75" >
<Border.Width>
<MultiBinding Converter="{StaticResource ReflectWidthConv}">
<Binding ElementName="HighlightBorder" Path="ActualWidth" />
<Binding ElementName="HighlightBorder" Path="BorderThickness" />
</MultiBinding>
</Border.Width>
<Border.Background>
<VisualBrush Visual="{Binding ElementName=ThumbImg}">
<VisualBrush.Transform>
<ScaleTransform ScaleX="1" ScaleY="-1" CenterX="200">
<ScaleTransform.CenterY>
<MultiBinding Converter="{StaticResource ReflectCenterYConv}">
<Binding ElementName="ThumbImg" Path="ActualHeight" />
</MultiBinding>
</ScaleTransform.CenterY>
</ScaleTransform>
</VisualBrush.Transform>
</VisualBrush>
</Border.Background>
<Border.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1.3">
<GradientStop Offset="0" Color="Black"></GradientStop>
<GradientStop Offset="0.1" Color="Transparent"></GradientStop>
</LinearGradientBrush>
</Border.OpacityMask>
</Border>
<!--<Label x:Name="ThumbTitle" Grid.Row="1" Content="{Binding Path=Title}" HorizontalAlignment="Center"></Label>-->
<Label x:Name="ThumbTitle" Grid.Row="1" Content="{Binding ElementName=ThumbInnerGrid, Path=ActualHeight, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center"></Label>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled" />
<Setter Property="Background" Value="Black"/>
</Style>
</UserControl.Resources>
<UserControl.DataContext>
<ObjectDataProvider ObjectType="{x:Type local:ThumbImageLoader}" MethodName="LoadImagesv2" IsAsynchronous="True" />
</UserControl.DataContext>
<!-- This ListBox is the Content of the Window. Normally you would have a panel of some type as the Window's Content, but let's keep it simple. -->
<Grid x:Name="ThumbListBoxGrid">
<ListBox x:Name="ThumbListBox" ItemsSource="{Binding}" VerticalAlignment="Top" Height="{Binding ElementName=ThumbListBoxGrid, Path=ActualHeight}" IsSynchronizedWithCurrentItem="True" />
</Grid>
Anyone see what's wrong here?
You specify the SelectedItem Background for a ListBox with the SystemColors.HighlightBrushKey (focused) and SystemColors.ControlBrushKey (not focused)
<Style TargetType="{x:Type ListBox}">
<Style.Resources>
<!-- Background of selected item when focussed -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="White"/>
<!-- Background of selected item when not focussed -->
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"
Color="White" />
</Style.Resources>
<!--...-->
</Style>
For anyone searching for this in the future, the accepted answer doesn't actually apply the colour when control is not focused for me. The following should be used instead which appears to work as intended.
<Style TargetType="ListBox">
<Style.Resources>
<!-- Background of selected item when focussed -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#FFFFB733" />
<!-- Background of selected item when not focussed -->
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="#FFFFB733"/>
</Style.Resources>
</Style>
I have a DataTrigger that I recently refactored. It used to have the DataContext set to be a ListBoxItem. Now it is a ContentPresenter.
Here is the code:
<DataTemplate.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource DisableWorkItemConverter}">
<Binding ElementName="MainForm" Path="PickedWorkItemID"/>
<Binding Path="WorkItemForColumn.Id"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="IsEnabled" Value="False"/>
<Setter Property="loc:Main.IsCurrentItemEnabledChanged" Value="True"/>
</DataTrigger>
</DataTemplate.Triggers>
In the OnChange of IsCurrentItemEnabledChanged I can see that I can get at the ListBoxItem with the following code (in the code behind):
listBoxItem = (ListBoxItem)Main.Instance.lstQueryResults.ItemContainerGenerator.
ContainerFromItem(((ContentPresenter)d).Content);
However, there is no way that I can see to set the DataContext such that my Setter for IsEnabled will set the enabled status of the ListBoxItem rather than the ContentPresenter.
(I would do it in the OnChange of IsCurrentItemEnabledChanged, but that property is already a bit of a hack and it will not re-enable the item when the trigger is set to false.)
Any ideas?
It was suggested that I provide more to provide context:
Here is my XAML for the templates.
<DataTemplate x:Key="ColumnTemplate">
<Border Name="ItemBorder" BorderBrush="Black" BorderThickness="1" CornerRadius="2" Padding="2">
<WrapPanel>
<TextBlock Margin="0,0,5,0">
<TextBlock.Text>
<Binding Path="Name" Converter="{StaticResource GetVisibilityOfColumnTitles}"/>
</TextBlock.Text>
</TextBlock>
<TextBlock Text="{Binding Value}" Margin="0,0,10,0" FontWeight="Bold" />
</WrapPanel>
</Border>
</DataTemplate>
<DataTemplate x:Key="RowTemplate">
<Border x:Name="ItemBorder" BorderThickness="1" BorderBrush="#D4D4FF">
<Grid x:Name="ItemGrid" Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsPresenter}}, Path=ActualWidth}" ScrollViewer.CanContentScroll="True" Margin="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<Grid.Background>
<Binding Path="WorkItemForColumn.Type" Converter="{StaticResource WorkItemTypeToColorConverter}" />
</Grid.Background>
<CheckBox VerticalAlignment="Center" Grid.Column="0" IsChecked="{Binding
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}},
Mode=TwoWay, Path=IsSelected}" Name="chkIsSelected" />
<ItemsControl Grid.Column="1" Margin="5,0,5,0" ItemsSource="{Binding}" ItemTemplate="{StaticResource ColumnTemplate}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"></WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<Button HorizontalAlignment="Right" x:Name="btnPick" Grid.Column="3" Style="{StaticResource roundButton}" Width="15" Height="15" Tag="{Binding WorkItemForColumn.Id}" Margin="5,0,10,0">
<Path Fill="DarkBlue">
<Path.Data>
<PathGeometry>
<PathFigure StartPoint="2,0" IsClosed="True">
<LineSegment Point="7,5"/>
<LineSegment Point="2,10"/>
</PathFigure>
<PathFigure StartPoint="2,2" IsClosed="True">
<LineSegment Point="5,5"/>
<LineSegment Point="2,8"/>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
</Button>
</Grid>
</Border>
<DataTemplate.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource DisableWorkItemConverter}">
<Binding ElementName="MainForm" Path="PickedWorkItemID"/>
<Binding Path="WorkItemForColumn.Id"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="IsEnabled" Value="False"/>
<Setter Property="loc:Main.IsCurrentItemEnabledChanged" Value="True"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
Here is the XAML for the List Box:
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled" Button.Click="PickWorkItem_Click" SelectionMode="Multiple" ItemTemplate="{StaticResource RowTemplate}" Name="lstQueryResults" SelectionChanged="lstQueryResults_SelectionChanged" >
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black"/>
</Style.Resources>
</Style>
</ListBox.Resources>
</ListBox>
The DataContext is set in the Code like so:
private void ChangeQueryResultListSource(WorkItemCollection queryResults, bool b)
{
// Un-hook the selection event while we change the ItemsSource
Form.ToggleOnSelectEvent(false);
// This sets the DataContext
QueryDisplay = GetDisplayValues(queryResults);
Form.QueryResultListSource = QueryDisplay;
// Rewire the selection events back in
Form.ToggleOnSelectEvent(true);
foreach (WorkItem item in Pad.Keys)
{
Form.SelectQueryResultItem(item);
}
}
private List<List<WorkItemColumn>> GetDisplayValues(WorkItemCollection queryResults)
{
var result = new List<List<WorkItemColumn>>();
foreach (WorkItem workItem in queryResults)
{
var row = GetQueryColumns(queryResults.DisplayFields, workItem);
result.Add(row);
}
return result;
}
private List<WorkItemColumn> GetQueryColumns(DisplayFieldList fields, WorkItem workItem)
{
var row = new List<WorkItemColumn>();
foreach (FieldDefinition column in fields)
{
var workItemColumn = new WorkItemColumn { Name = column.Name, Value = workItem[column.Name], WorkItemForColumn = workItem };
row.Add(workItemColumn);
}
return row;
}
WorkItemColumn is a class with a Name-Value pair and a reference to the data (a WorkItem object).
Sorry for the short answer, but you should move the trigger and setter logic for IsEnabled back to the ListBoxItem style:
<Style TargetType="{x:Type ListBoxItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black"/>
</Style.Resources>
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource DisableWorkItemConverter}">
<Binding ElementName="MainForm" Path="PickedWorkItemID"/>
<Binding Path="WorkItemForColumn.Id"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>