Animations Slow As Window Size Increases - wpf

I've started to build a Wpf app by re-templating the chrome of the main window. My chrome template contains 4 buttons which each have a template that displays a border with an image inside and uses a trigger and colour animation to re-colour the border to provide a mouse over effect. The rest of the template is static and the content of the window is a button (just to display something). I do have AllowTransparency set to True.
The problem I've got is when the window is small (say 800w x 500h) the animations run fine, they start the moment the mouse enters and play at the correct speed but as I make the window larger the animations slow down and there starting lags the mouse entering the button until the window is maximized where you have to leave the mouse sitting over the button for a period of time before the animation plays and when it does its very jerky and slow.
I have tried the following to track down this issue but to no avail:
Made sure that only the xaml animations were playing no vb or other event handlers were being executed at the same time.
Defined Height, Width, and ZIndex values on the containing StackPanel so hopefully?? wpf would only redraw the StackPanel contents.
Removed 3 of the 4 buttons.
Tried it on different screens (which use different graphics cards).
Reconfigured my system so it only used one screen.
Made sure hardware acceleration was on.
Ran Resource Monitor and noticed that when the window is small constantly mousing across the buttons uses about 2% of my cpu resources but when the window is maximized is uses about 23%.
I'm guessing that wpf is redrawing a lot more than I expect but I don't know how to stop that if that is the case.
Any help would be very much welcomed.
Sorry for the huge list of Xaml.
Window:
<Window x:Class="Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowState="{Binding ShellState,
Mode=OneWayToSource}"
Title="{Binding Title,
Mode=OneTime}"
Style="{Binding ShellStyling,
Mode=OneTime}"
WindowStartupLocation="CenterScreen"><!-- ShellStyling = MainWindowShellStyle-->
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="{Binding TitleHeight,
Mode=OneTime}"
ResizeBorderThickness="{Binding ResizeBorderThickness,
Mode=OneTime}"
GlassFrameThickness="0"/>
</WindowChrome.WindowChrome>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentControl Name="Stage"
Grid.Column="0"
Grid.Row="1"/>
</Grid>
</Window>
Styles:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key = "ChromeButtonBaseStyle"
TargetType = "{x:Type Button}">
<Setter Property = "Template"
Value = "{StaticResource MizedButtonTemplate}"/>
<Setter Property = "WindowChrome.IsHitTestVisibleInChrome"
Value = "True"/>
<Setter Property = "SnapsToDevicePixels"
Value = "True"/>
<Setter Property = "ToolTipService.Placement"
Value = "Bottom"/>
<Setter Property = "ToolTipService.ShowOnDisabled"
Value = "True"/>
<Setter Property = "VerticalAlignment"
Value = "Bottom"/>
<Setter Property = "HorizontalAlignment"
Value = "Center"/>
</Style>
<Style x:Key = "ChromeButtonImageBaseStyle"
TargetType = "Image">
<Setter Property = "SnapsToDevicePixels"
Value = "True"/>
<Setter Property = "ToolTipService.Placement"
Value = "Bottom"/>
<Setter Property = "Stretch"
Value = "None"/>
<Setter Property = "RenderOptions.BitmapScalingMode"
Value = "NearestNeighbor"/>
<Setter Property = "WindowChrome.IsHitTestVisibleInChrome"
Value = "True"/>
</Style>
<Style x:Key = "ChromeButtonImageStyle"
TargetType = "Image"
BasedOn = "{StaticResource ChromeButtonImageBaseStyle}">
<Setter Property = "Height"
Value = "{Binding ImageHeight,
Mode=OneTime}"/>
<Setter Property = "Width"
Value = "{Binding ImageWidth,
Mode=OneTime}"/>
</Style>
<Style x:Key = "ChromeButtonsContainerStyle"
TargetType = "Border">
<Setter Property = "Background"
Value = "{StaticResource BackgroundBrush}"/>
</Style>
<Style x:Key = "ChromeButtonsInnerContainerStyle"
TargetType = "{x:Type StackPanel}">
<Setter Property = "Orientation"
Value = "Horizontal"/>
<Setter Property = "VerticalAlignment"
Value = "Bottom"/>
</Style>
<Style TargetType = "{x:Type Button}"
x:Key = "ChromeButtonStyle"
BasedOn = "{StaticResource ChromeButtonBaseStyle}">
<Setter Property = "Border.CornerRadius"
Value = "{Binding CornerRadius,
Mode=OneTime}"/>
<Setter Property = "Padding"
Value = "{Binding ImagePadding,
Mode=OneTime}"/>
<Setter Property = "Margin"
Value = "{Binding ImageMargin,
Mode=OneTime}"/>
<Setter Property = "ToolTipService.VerticalOffset"
Value = "{Binding ToolTipVerticalOffset,
Mode=OneTime}"/>
<Setter Property = "ToolTipService.HorizontalOffset"
Value = "{Binding ToolTipHorizontalOffset,
Mode=OneTime}"/>
</Style>
<Style TargetType = "{x:Type Button}"
x:Key = "CloseButtonStyle"
BasedOn = "{StaticResource ChromeButtonStyle}">
<Setter Property = "Template"
Value = "{StaticResource CloseButtonTemplate}"/>
<Setter Property = "ToolTipService.ToolTip"
Value = "{Binding ToolTipText}"/>
<EventSetter Event = "Click"
Handler = "HandleCloseWindow" />
</Style>
<Style x:Key = "ContainerGridStyle"
TargetType = "Grid">
<Setter Property = "Background"
Value = "Transparent"/>
</Style>
<Style x:Key = "ContentContainerStyle"
TargetType = "Border">
<Setter Property = "Background"
Value = "{StaticResource BackgroundBrush}"/>
</Style>
<Style x:Key = "GripHandleStyle"
TargetType = "Image">
<Setter Property = "Width"
Value = "{Binding GripHandleWidth,
Mode=OneTime}"/>
<Setter Property = "Height"
Value = "{Binding TitleHeight,
Mode=OneTime}"/>
<Setter Property = "Stretch"
Value = "None"/>
<Setter Property = "SnapsToDevicePixels"
Value = "True"/>
<Setter Property = "Margin"
Value = "0"/>
<Setter Property = "HorizontalAlignment"
Value = "Right"/>
<Setter Property = "Source"
Value = "{Binding GripHandleDefinition,
Mode=OneTime}"/>
<Setter Property = "RenderOptions.BitmapScalingMode"
Value = "NearestNeighbor"/>
</Style>
<Style x:Key = "InnerBorderStyle"
TargetType = "{x:Type Border}">
<Setter Property = "Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth = "0"
BlurRadius = "8"
RenderingBias = "Quality"/>
</Setter.Value>
</Setter>
</Style>
<Style x:Key = "MaximizeButtonStyle"
TargetType = "Button"
BasedOn = "{StaticResource ChromeButtonStyle}">
<Setter Property = "ToolTipService.ToolTip"
Value = "{Binding ToolTipText}"/>
<EventSetter Event = "Click"
Handler = "HandleMaximizeWindow"/>
</Style>
<Style x:Key = "MinimizeButtonStyle"
TargetType = "Button"
BasedOn = "{StaticResource ChromeButtonStyle}">
<Setter Property = "ToolTipService.ToolTip"
Value = "{Binding ToolTipText}"/>
<EventSetter Event = "Click"
Handler = "HandleMinimizeWindow"/>
</Style>
<Style x:Key = "OuterBorderStyle"
TargetType = "{x:Type Border}">
<Setter Property = "BorderThickness"
Value = "0"/>
<Setter Property = "BorderBrush"
Value = "{x:Null}"/>
<Setter Property = "Background"
Value = "Transparent"/>
<Setter Property = "Padding"
Value = "{Binding RelativeSource = {RelativeSource TemplatedParent},
Path=DataContext.OuterMarginThickness,
Mode=OneWay}"/>
</Style>
<Style x:Key = "TitleLayoutStyle"
TargetType = "StackPanel">
<Setter Property = "Orientation"
Value = "Horizontal"/>
<Setter Property = "Height"
Value = "{Binding TitleHeight,
Mode=OneTime}"/>
</Style>
<Style x:Key = "TitleTextBaseStyle"
TargetType = "{x:Type TextBlock}">
<Setter Property = "FontFamily"
Value = "Segoe UI"/>
<Setter Property = "Foreground"
Value = "{StaticResource TitleBrush}"/>
<Setter Property = "VerticalAlignment"
Value = "Bottom"/>
<Setter Property = "Background"
Value = "Transparent"/>
<Setter Property = "Text"
Value = "{Binding Title,
Mode=OneTime}"/>
</Style>
<Style x:Key = "TitleTextStyle"
TargetType = "TextBlock"
BasedOn = "{StaticResource TitleTextBaseStyle}">
<Setter Property = "FontSize"
Value = "{Binding TitleTextFontSize,
Mode=OneTime}"/>
<Setter Property = "Margin"
Value = "{Binding TitleTextMargin,
Mode=OneTime}"/>
</Style>
<Style x:Key = "WindowShellBaseStyle"
TargetType = "{x:Type Window}">
<Setter Property = "OverridesDefaultStyle"
Value = "True"/>
<Setter Property = "WindowStyle"
Value = "None"/>
<Setter Property = "AllowsTransparency"
Value = "True"/>
</Style>
<Style x:Key = "MainWindowShellStyle"
TargetType = "{x:Type Window}"
BasedOn = "{StaticResource WindowShellBaseStyle}">
<Setter Property = "Height"
Value = "{Binding Height}"/>
<Setter Property = "Width"
Value = "{Binding Width}"/>
<Setter Property = "MaxHeight"
Value = "{Binding MaxHeight}"/>
<Setter Property = "MaxWidth"
Value = "{Binding MaxWidth}"/>
<Setter Property = "MinHeight"
Value = "{Binding MinHeight}"/>
<Setter Property = "MinWidth"
Value = "{Binding MinWidth}"/>
<Setter Property = "ShowInTaskbar"
Value = "{Binding ShowInTaskBar}"/>
</Style>
</ResourceDictionary>
Templates:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source = "pack://application:,,,/WindowChromeColors.xaml"/>
<ResourceDictionary
Source = "pack://application:,,,/WindowChromeAnimations.xaml"/>
</ResourceDictionary.MergedDictionaries>
<ControlTemplate TargetType = "{x:Type Button}"
x:Key = "CloseButtonTemplate">
<Border Padding = "{TemplateBinding Padding}"
Margin = "{TemplateBinding Margin}"
BorderThickness = "{TemplateBinding BorderThickness}"
CornerRadius = "{TemplateBinding Border.CornerRadius}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
SnapsToDevicePixels = "True">
<Border.BorderBrush>
<SolidColorBrush x:Name = "HoverBorderColor"
Color = "{StaticResource MouseOutBorder}"/>
</Border.BorderBrush>
<Border.Background>
<SolidColorBrush x:Name = "ButtonBackground"
Color = "{StaticResource Background}"/>
</Border.Background>
<Image Source="{Binding ImageSource}"
Style="{Binding ImageStyle}" />
</Border>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent = "MouseEnter">
<BeginStoryboard>
<Storyboard TargetName = "HoverBorderColor">
<!-- ReSharper disable once Xaml.InvalidResourceType -->
<StaticResource ResourceKey = "HoverBorderAnimation"/>
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard TargetName = "ButtonBackground">
<!-- ReSharper disable once Xaml.InvalidResourceType -->
<StaticResource ResourceKey = "CloseButtonHoverBgAnimation"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent = "MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard TargetName = "HoverBorderColor">
<!-- ReSharper disable once Xaml.InvalidResourceType -->
<StaticResource ResourceKey = "LeaveBorderAnimation"/>
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard TargetName = "ButtonBackground">
<!-- ReSharper disable once Xaml.InvalidResourceType -->
<StaticResource ResourceKey = "CloseButtonLeaveBgAnimation"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate TargetType="{x:Type Button}"
x:Key="MizedButtonTemplate">
<Border Padding="{TemplateBinding Padding}"
Margin="{TemplateBinding Margin}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding Border.CornerRadius}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
SnapsToDevicePixels="True"
Background="{StaticResource BackgroundBrush}"
>
<Border.BorderBrush>
<SolidColorBrush x:Name="HoverBorderColor"
Color="{StaticResource MouseOutBorder}" />
</Border.BorderBrush>
<Image Source="{Binding ImageSource}"
Style="{Binding ImageStyle}"/>
</Border>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard TargetName="HoverBorderColor">
<!--ReSharper disable once Xaml.InvalidResourceType-->
<StaticResource ResourceKey="HoverBorderAnimation" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard TargetName="HoverBorderColor">
<!--ReSharper disable once Xaml.InvalidResourceType-->
<StaticResource ResourceKey="LeaveBorderAnimation" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="WindowShellTemplate"
TargetType="{x:Type Window}">
<Border Style="{StaticResource OuterBorderStyle}">
<Border Style="{StaticResource InnerBorderStyle}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Column="0"
Grid.Row="0"
Style="{StaticResource ContainerGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Grid.Column="0"
Grid.Row="0"
Style="{StaticResource GripHandleStyle}"/>
<Border Grid.Column="2"
Grid.Row="0"
Style="{StaticResource ChromeButtonsContainerStyle}">
<StackPanel Style="{StaticResource ChromeButtonsInnerContainerStyle}">
<TextBlock Grid.Column="1"
Grid.Row="0"
Style="{StaticResource TitleTextStyle}" />
<Button DataContext="{Binding MinimizeButtonViewModel,
Mode=OneTime}"
Style="{StaticResource MinimizeButtonStyle}"
Visibility="{Binding Visibility,
Mode=OneTime}"
Tag = "{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}},
Mode=OneTime}" />
<Button DataContext="{Binding MaximizeButtonViewModel,
Mode=OneTime}"
Style="{StaticResource MaximizeButtonStyle}"
Visibility="{Binding Visibility,
Mode=OneTime}"
Tag = "{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}},
Mode=OneTime}" />
<Button DataContext="{Binding CloseButtonViewModel,
Mode=OneTime}"
Style="{StaticResource CloseButtonStyle}"
Visibility="{Binding Visibility,
Mode=OneTime}"
Tag="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}},
Mode=OneWay}"
Command = "{Binding ClickAction,
Mode=OneTime}"
CommandParameter = "{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}},
Mode=OneTime}" />
</StackPanel>
</Border>
</Grid>
<Border Grid.Column="0"
Grid.Row="1"
Style="{StaticResource ContentContainerStyle}">
<ContentPresenter />
</Border>
</Grid>
</Border>
</Border>
</ControlTemplate>
</ResourceDictionary>
Animations All the colour animations are the same as the one below they just animate different colours.
<ColorAnimation x:Key="HoverBorderAnimation"
Storyboard.TargetProperty="Color"
To="{StaticResource MouseHoverBorder}"
Duration="0:0:0.25"
AutoReverse="False" />

Related

wpf TreeView binding having multiple TreeViewItemStyle

i'm able to create dinamicaly both RadioButtions and CheckBoxes inside TreeViewItem using this code in Window1.cs initialization:
TreeViewItem parent = createTextInTree("Выпечка", tree);
createCheckBoxChildren("торт Птичье молоко - 350 звезд", parent);
createCheckBoxChildren("пироженное Тирамиссу - 25 UAH", parent);
createCheckBoxChildren("пироженное Тирамиссу - 70 звезд", parent);
createCheckBoxChildren("тарт Вишня - 35 звезд", parent);
parent = createTextInTree("Мороженное", tree);
createRadioButtonsChildren("ванильное - 15 звезд", parent, "grp1");
createRadioButtonsChildren("шоколадное - 15 звезд", parent, "grp1");
createRadioButtonsChildren("клубничное - 15 звезд", parent, "grp1");
parent = createTextInTree("Кофе", tree);
createRadioButtonsChildren("эспрессо - 30 звезд", parent, "grp2");
createRadioButtonsChildren("латте - 25 UAH", parent, "grp2");
createRadioButtonsChildren("латте - 50 звезд", parent, "grp2");
createRadioButtonsChildren("капучино - 35 звезд", parent, "grp2");
There methods are:
private TreeViewItem createTextInTree(string content, TreeView tree)
{
TreeViewItem item = new TreeViewItem()
{
Header = content
};
tree.Items.Add(item);
return item;
}
private TreeViewItem createCheckBoxInTree(string content, TreeView tree)
{
TreeViewItem item = new TreeViewItem()
{
Header = new CheckBox()
{
Content = content
}
};
tree.Items.Add(item);
return item;
}
private void createCheckBoxChildren(string content, TreeViewItem item)
{
TreeViewItem child = new TreeViewItem()
{
Header = new CheckBox()
{
Content = content,
}
};
item.Items.Add(child);
}
private void createRadioButtonsChildren(string content, TreeViewItem item, string group)
{
TreeViewItem childRadio = new TreeViewItem()
{
Header = new RadioButton()
{
Content = content,
GroupName = group,
}
};
item.Items.Add(childRadio);
}
Control now looks like that:
Control dialog
Using example: TreeView with Checkboxes I was succeded to use bindings in case i have only one model for TreeViewItem, but not in case i have multiple ones.
Here is my current xaml:
<Window.Resources>
<ResourceDictionary.MergedDictionaries>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="TreeViewItemStyle" TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True" />
<Setter Property="IsSelected" Value="{Binding IsInitiallySelected, Mode=OneTime}" >
<Setter Property="KeyboardNavigation.AcceptsReturn" Value="True" />
<Setter Property="dw:VirtualToggleButton.IsVirtualToggleButton" Value="True" />
<Setter Property="dw:VirtualToggleButton.IsChecked" Value="{Binding IsChecked}" />
<Setter Property="FontSize" Value="30"/>
</Style>
<Style TargetType="{x:Type TreeView}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#CBE8F6" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" />
</Style.Resources>
</Style>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="BorderThickness" Value="1" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderBrush" Value="#26A0DA" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True" />
<Condition Property="IsSelectionActive" Value="False" />
</MultiTrigger.Conditions>
<Setter Property="BorderBrush" Value="#DADADA" />
</MultiTrigger>
</Style.Triggers>
</Style>
<HierarchicalDataTemplate x:Key="RadioButtonItemTemplate" DataType="{x:Type local:FooViewModel2}" ItemsSource="{Binding Children, Mode=OneTime}">
<StackPanel Orientation="Horizontal">
<RadioButton Focusable="False" IsChecked="{Binding IsChecked}" VerticalAlignment="Center" />
<ContentPresenter Content="{Binding Name, Mode=OneTime}" Height="30" Margin="8,0" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="CheckBoxItemTemplate" DataType="{x:Type local:FooViewModel}" ItemsSource="{Binding Children, Mode=OneTime}" >
<StackPanel Orientation="Horizontal">
<!-- These elements are bound to a FooViewModel object. -->
<CheckBox Focusable="False" IsChecked="{Binding IsChecked}" VerticalAlignment="Center" />
<ContentPresenter Content="{Binding Name, Mode=OneTime}" Height="30" Margin="8,0" />
</StackPanel>
</HierarchicalDataTemplate>
</ResourceDictionary>
</Window.Resources>
<Window.DataContext>
</Window.DataContext>
<DockPanel>
<TreeView x:Name="tree" Width="450" ItemContainerStyle="{StaticResource TreeViewItemStyle}" ItemsSource="{Binding Mode=OneTime}" ItemTemplate="{StaticResource RadioButtonItemTemplate}" />
<StackPanel Background="White">
<Button Command="Undo" Content="Uncheck All" HorizontalAlignment="Stretch" Margin="0,2" Padding="8,0"/>
<Button DockPanel.Dock="Bottom" Content="Ok" HorizontalAlignment="Stretch" Margin="0,2" Padding="8,0"/>
<Button DockPanel.Dock="Bottom" IsCancel="True" IsDefault="True" Content="Отмена" HorizontalAlignment="Stretch" Margin="0,2" Padding="8,0"/>
<Label Name="lblTotalBonusesTitle" Content="Всего бонусов" HorizontalAlignment="Center" FontWeight="Bold" Margin="0,2" Padding="1,0" />
<Label Name="lblTotalBonuses" Content="750" HorizontalAlignment="Center" Margin="0,2" Padding="1,0" />
<Label Name="lblChosenBonusesTitle" Content="Выбрано" HorizontalAlignment="Center" FontWeight="Bold" Margin="0,2" Padding="1,0" />
<Label Name="lblChosenBonuses" Content="320" HorizontalAlignment="Center" FontWeight="DemiBold" Margin="0,2" Padding="1,0" />
<Label Name="lblChosenStrTitle" Content="Выбраны" HorizontalAlignment="Center" FontWeight="Bold" Margin="0,2" Padding="1,0" />
<Label Name="lblChosenStr" Content="" HorizontalAlignment="Center" FontWeight="DemiBold" Margin="0,2" Padding="1,0" />
</StackPanel>
</DockPanel>
I settled on using a DataTemplateSelector. This is a custom class with a method that returns a DataTemplate based on whatever criteria you need. The custom DataTemplateSelector is then assigned to the element: in the case of ListBox it is the ItemTemplateSelector property.

How can I vary the layout of a UserControl by a Property?

I've made the smallest project I can to demonstrate the problem:
Code behind:
public partial class AxisControl : UserControl
{
public static readonly DependencyProperty LayoutProperty =
DependencyProperty.Register("Layout", typeof(Orientation), typeof(AxisControl),
new PropertyMetadata(Orientation.Horizontal));
public Orientation Layout
{
get { return (Orientation)GetValue(LayoutProperty); }
set { SetValue(LayoutProperty, value); }
}
public AxisControl()
{
InitializeComponent();
}
}
Xaml:
<UserControl.Resources>
<ContentControl x:Key="horizontalLayout" Height="60">
<TextBlock Text="{Binding Layout, RelativeSource={RelativeSource AncestorType=UserControl}}" HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
</ContentControl>
<ContentControl x:Key="verticalLayout" Width="60">
<TextBlock Text="{Binding Layout, RelativeSource={RelativeSource AncestorType=UserControl}}" HorizontalAlignment="Left" VerticalAlignment="Center">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"/>
</TextBlock.LayoutTransform>
</TextBlock>
</ContentControl>
</UserControl.Resources>
<UserControl.Style>
<Style TargetType="UserControl">
<Style.Setters>
<Setter Property="Content" Value="{StaticResource horizontalLayout}"/>
</Style.Setters>
<Style.Triggers>
<DataTrigger Binding="{Binding Layout, ElementName=root}" Value="Vertical">
<Setter Property="Content" Value="{StaticResource verticalLayout}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Style>
Edit: Xaml now includes the elements I want to arrange in the UserControl.
MainWindow Xaml:
<Grid>
<local:AxisControl Layout="Vertical"/>
</Grid>
The idea is to set the layout of the UserControl according to its Layout property so I put both layouts in static resources and made a Style to set the Content to the one I want according to Layout which is of type Orientation.
Edit: I want the Content to include elements arranged in a different order according to the Orientation.
The UserControl displays correctly but there's an error in the output window that concerns me:
Cannot find source for binding with reference 'RelativeSource
FindAncestor, AncestorType='System.Windows.Controls.UserControl',
AncestorLevel='1''. BindingExpression:Path=Layout; DataItem=null;
target element is 'TextBlock' (Name=''); target property is 'Text'
(type 'String')
Does this mean it's trying to do a Binding before it's in the visual tree possibly from the Trigger?
Note the use of RelativeSource and ElementName in the Bindings as it's incorrect to set the DataContext at the root of a UserControl because it breaks the DataContext inheritance.
What am I doing wrong and how can I get rid of the error?
Inspired by Clemens comment and further research I realized I needed a ControlTemplate resource for each layout and not resources containing instances of the elements themselves.
<UserControl.Resources>
<ControlTemplate x:Key="horizontalLayout">
<Border Height="60" Background="LightBlue">
<TextBlock Text="{Binding Layout, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="verticalLayout" TargetType="UserControl">
<Border Width="60" Background="LightBlue">
<TextBlock Text="{Binding Layout, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Left" VerticalAlignment="Center">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"/>
</TextBlock.LayoutTransform>
</TextBlock>
</Border>
</ControlTemplate>
</UserControl.Resources>
<UserControl.Style>
<Style TargetType="UserControl">
<Style.Setters>
<Setter Property="Template" Value="{StaticResource horizontalLayout}"/>
</Style.Setters>
<Style.Triggers>
<DataTrigger Binding="{Binding Layout, ElementName=root}" Value="Vertical">
<Setter Property="Template" Value="{StaticResource verticalLayout}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Style>
Layout = Horizontal
Layout = Vertical

WPF chart heavy cpu usage on update itemsource

First of all i want to apologize, because i don't know how to ask the question the right way.
I'm not sure how to describe the problem i have.
There is a page in my wpf-application where i draw some lineseries on a chart.
<Page x:Class="Zentralvakuum_Archivauswertung.Views.Zentrale"
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:Zentralvakuum_Archivauswertung.Views"
xmlns:DV="clr-namespace:System.Windows.Controls.DataVisualization;assembly=System.Windows.Controls.DataVisualization.Toolkit"
xmlns:DVC="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
DataContext="{Binding Source={StaticResource ViewModelLocator}, Path=ZentraleVm}"
d:DesignHeight="300" d:DesignWidth="300"
Title="Zentrale">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DVC:Chart Name="Chart" Width="auto" Height="auto" Title="Something" grid.row="0">
<DVC:Chart.Series>
<DVC:LineSeries Title="1"
IndependentValueBinding="{Binding Path=Key}"
DependentValueBinding="{Binding Path=Value}" ItemsSource="{Binding Istwerte1Liste, UpdateSourceTrigger=PropertyChanged}" >
<DVC:LineSeries.DataPointStyle>
<Style TargetType="DVC:LineDataPoint">
<Setter Property="Template" Value="{x:Null}" />
<Setter Property="Background" Value="Black"/>
<Setter Property="Opacity" Value="0" />
</Style>
</DVC:LineSeries.DataPointStyle>
</DVC:LineSeries>
<DVC:LineSeries Title="1a"
IndependentValueBinding="{Binding Path=Key}"
DependentValueBinding="{Binding Path=Value}" ItemsSource="{Binding Sollwerte1Liste, UpdateSourceTrigger=PropertyChanged}">
<DVC:LineSeries.DataPointStyle>
<Style TargetType="DVC:LineDataPoint">
<Setter Property="Template" Value="{x:Null}" />
<Setter Property="Background" Value="Green"/>
<Setter Property="Opacity" Value="0" />
</Style>
</DVC:LineSeries.DataPointStyle>
</DVC:LineSeries>
<DVC:LineSeries Title="2"
IndependentValueBinding="{Binding Path=Key}"
DependentValueBinding="{Binding Path=Value}" ItemsSource="{Binding Istwerte2Liste, UpdateSourceTrigger=PropertyChanged}" >
<DVC:LineSeries.DataPointStyle>
<Style TargetType="DVC:LineDataPoint">
<Setter Property="Template" Value="{x:Null}" />
<Setter Property="Background" Value="Blue"/>
<Setter Property="Opacity" Value="0" />
</Style>
</DVC:LineSeries.DataPointStyle>
</DVC:LineSeries>
<DVC:LineSeries Title="2a"
IndependentValueBinding="{Binding Path=Key}"
DependentValueBinding="{Binding Path=Value}" ItemsSource="{Binding Sollwerte2Liste, UpdateSourceTrigger=PropertyChanged}">
<DVC:LineSeries.DataPointStyle>
<Style TargetType="DVC:LineDataPoint">
<Setter Property="Template" Value="{x:Null}" />
<Setter Property="Background" Value="Red"/>
<Setter Property="Opacity" Value="0" />
</Style>
</DVC:LineSeries.DataPointStyle>
</DVC:LineSeries>
</DVC:Chart.Series>
</DVC:Chart>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" HorizontalAlignment="Center">
<Label DockPanel.Dock="Top" HorizontalAlignment="Center" FontWeight="Bold" FontSize="20" Content="Start:"/>
<xctk:DateTimePicker Value="{Binding Start, UpdateSourceTrigger=PropertyChanged}" Format="FullDateTime" ShowDropDownButton="False" HorizontalContentAlignment="Center"/>
<Button Content="Actualize" Command="{Binding ActualizeCommand}"/>
</StackPanel>
<StackPanel Grid.Column="1" HorizontalAlignment="Center">
<Label DockPanel.Dock="Top" HorizontalAlignment="Center" FontWeight="Bold" FontSize="20" Content="Ende:"/>
<xctk:DateTimePicker Value="{Binding End, UpdateSourceTrigger=PropertyChanged}" Format="FullDateTime" ShowDropDownButton="False" HorizontalContentAlignment="Center"/>
<Button Content="Actualize" Command="{Binding ActualizeCommand}"/>
</StackPanel>
</Grid>
</Grid>
The first time these page is opened everything goes fine, page opens, lineseries are drawn and done.
When i update the itemsources of the lineseries, lineseries are drawn and ... applicationfreeze for a long time caused of heavy cpu usage. I linked an image of this.
green square = frist opening of the page, red square = update of itemsource (green bar = chart updated, all my code is done)
Following the update funtion:
public void Actualize()
{
WerteZentrale = null;
WerteZentraleCollection = null;
//Get values from db
WerteZentrale = new Vakuumverlauf_ZentraleEntities1();
WerteZentraleCollection = new ListCollectionView((from a in WerteZentrale.Werte_Zentrale0 where a.TimeString != string.Empty select a).ToList());
//filter
WerteZentraleCollection.Filter = (found) =>
{
Werte_Zentrale0 a = found as Werte_Zentrale0;
return (Convert.ToDateTime(a.TimeString) >= Start && Convert.ToDateTime(a.TimeString) <= Ende);
};
//sort
WerteZentraleCollection.CustomSort = new DateTimeComparerWerte();
//empty observablecollections
Istwerte1ListeDummy.Clear();
Sollwerte1ListeDummy.Clear();
Istwerte2ListeDummy.Clear();
Sollwerte2ListeDummy.Clear();
Istwerte1Liste.Clear();
Sollwerte1Liste.Clear();
Istwerte2Liste.Clear();
Sollwerte2Liste.Clear();
foreach (Werte_Zentrale0 Wert in WerteZentraleCollection)
{
//1
if (Wert.VarName == "VakuumWerte_VK1_Istwert_Istwert")
{
Istwerte1ListeDummy.Add(new KeyValuePair<DateTime, double?>(Convert.ToDateTime(Wert.TimeString), Wert.VarValue));
}
//1a
if (Wert.VarName == "VakuumWerte_VK1_Sollwert")
{
Sollwerte1ListeDummy.Add(new KeyValuePair<DateTime, double?>(Convert.ToDateTime(Wert.TimeString), Wert.VarValue));
}
//2
if (Wert.VarName == "VakuumWerte_VK2_Istwert_Istwert")
{
Istwerte2ListeDummy.Add(new KeyValuePair<DateTime, double?>(Convert.ToDateTime(Wert.TimeString), Wert.VarValue));
}
//2a
if (Wert.VarName == "VakuumWerte_VK2_Sollwert")
{
Sollwerte2ListeDummy.Add(new KeyValuePair<DateTime, double?>(Convert.ToDateTime(Wert.TimeString), Wert.VarValue));
}
}
//write to itemsource
Istwerte1Liste = Istwerte1ListeDummy;
Sollwerte1Liste = Sollwerte1ListeDummy;
Istwerte2Liste = Istwerte2ListeDummy;
Sollwerte2Liste = Sollwerte2ListeDummy;
}
This function is called in the constructor of the viewmodel, aswell as at the ActualizeCommand.
So for me, i'm doing the same thing in both cases but something different is the result and i have no clue why.

How To Find ScrollViewer Inside of WPF ContentControl?

WPF 4.5 / C#
I've got an app where I have several WPF Windows each utilizing this custom content control. I use it in the XAML like this:
<ContentControl Name="myControl" Style="{StaticResource ReservedSpaceScrollBar}"
In the code behind, I need to be able to access the ScrollViewer inside, so I can call .ScrollToTop()
I've tried this, but it doesn't work:
((ScrollViewer)this.myControl.FindName("Scroll")).ScrollToTop();
...but .FindName doesn't find the ScrollViewer. What am I doing wrong? How make this work?
The XAML for the Style is below...
<Style TargetType="{x:Type ContentControl}" x:Key="ReservedSpaceScrollBar">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<ScrollViewer PanningMode="Both" VerticalScrollBarVisibility="Auto" x:Name="Scroll" FocusVisualStyle="{x:Null}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter />
<Border Width="{x:Static SystemParameters.VerticalScrollBarWidth}" x:Name="Placeholder" Grid.Column="1" />
</Grid>
</ScrollViewer>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding ComputedVerticalScrollBarVisibility, ElementName=Scroll}" Value="Visible">
<Setter TargetName="Placeholder" Property="Visibility" Value="Collapsed" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Look into the VisualTreeHelper
Using that class you can look into children of elements; for example:
var childCount = VisualTreeHelper.GetChildrenCount(this.myControl);
for (int i = 0; i < childCount; i++)
{
var child = VisualTreeHelper.GetChild(this.myControl, i);
if (child.GetValue(NameProperty).ToString() == "Scroll")
{
((ScrollViewer)child).ScrollToTop();
}
}

image button template?

I want Image button with two state(normal , mouse over). that button must change image with Mouse Over event trigger automatically.
this image button must be a user control. Also i want to set image for each state form code in which form i use that user control.
Solution is using a template with "Value Converter" but i don't know how?
Why must this image button be a user control? If a regular button with a new control template is fine, this should work:
<Button>
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Image Name="HoverImage" Source="hover_image.png" Visibility="Hidden" />
<Image Name="DefaultImage" Source="default_image.png" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="DefaultImage" Property="Visibility" Value="Hidden" />
<Setter TargetName="HoverImage" Property="Visibility" Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
If you need a simple rollover effect, you don't need a template for it.. article below has a solution to it..
http://www.c-sharpcorner.com/Resources/Detail.aspx?ResourceId=706
In this article user uses SolidColorBrush, you can use ImageBrush to set image as background of button.
I found This on Code-project-Article(Cool example)
http://www.codeproject.com/KB/WPF/WPF_xaml_taskbar_window.aspx
First He create Wpf-Custom-control(you can create class inherit from Button like this)
public class ImageButton : Button
{
private string cornerRadius;
public string CornerRadius
{
get { return cornerRadius; }
set { cornerRadius = value; }
}
private string highlightBackground;
public string HighlightBackground
{
get { return highlightBackground; }
set { highlightBackground = value; }
}
private string pressedBackground;
public string PressedBackground
{
get { return pressedBackground; }
set { pressedBackground = value; }
}
}
As second step you must Create template in resource-dictionary(here is code)
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Phone.Controls">
<ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type local:ImageButton}">
<ControlTemplate.Resources>
<Storyboard x:Key="MouseOverButton">
<ThicknessAnimation Storyboard.TargetName="ButtonBackgroundBorder"
Storyboard.TargetProperty="(Control.Margin)"
Duration="0:0:0.05"
FillBehavior="Stop"
From="0,0,0,0" To="2,2,2,2"
AutoReverse="True" />
</Storyboard>
</ControlTemplate.Resources>
<Grid x:Name="ButtonOuterGrid">
<Border x:Name="ButtonBackgroundBorder"
CornerRadius="{Binding Path=CornerRadius, RelativeSource={RelativeSource TemplatedParent}}"
Background="{Binding Path=HighlightBackground, RelativeSource={RelativeSource TemplatedParent}}"
BorderBrush="Black"
BorderThickness="0.8"
Opacity="0">
<Border.BitmapEffect>
<OuterGlowBitmapEffect GlowColor="#FFFFFFFF" GlowSize="2.75" Noise="0.20"/>
</Border.BitmapEffect>
</Border>
<Border x:Name="ButtonEdgesBorder" CornerRadius="{Binding Path=CornerRadius, RelativeSource={RelativeSource TemplatedParent}}"
Opacity="1"
BorderBrush="Transparent"
BorderThickness="0" />
<Border x:Name="ButtonContentBorder"
CornerRadius="{Binding Path=CornerRadius, RelativeSource={RelativeSource TemplatedParent}}"
Opacity="1"
BorderThickness="1">
<ContentPresenter x:Name="ContentText"
Width="Auto" Height="Auto"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.Setters>
<Setter Property="Opacity" TargetName="ButtonBackgroundBorder" Value="1"/>
<Setter Property="TextElement.Foreground" TargetName="ContentText" Value="Black"/>
</Trigger.Setters>
</Trigger>
<EventTrigger RoutedEvent="Grid.MouseEnter"
SourceName="ButtonOuterGrid">
<BeginStoryboard Storyboard="{StaticResource MouseOverButton}"/>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="ImageButton" TargetType="{x:Type Button}">
<Setter Property="Template" Value="{StaticResource ButtonTemplate}" />
</Style>
And this is last Step, in xaml file you must insert this custom-control
<ImageButton x:Name="btnConfigs"
Style="{StaticResource ImageButton}"
Width="25" Height="25"
VerticalAlignment="Top"
HorizontalAlignment="Right"
Margin="0,31.125,16.418,0">
<Image x:Name="ImgConfigs"
Stretch="Fill"/>
</ImageButton >
and in cs file do this
this.ImgConfigs.Source="any imag-source"
also we can change this image-source on btnconfig-click event
With special thanks from Murray-Foxcroft for create that article

Resources