I'm trying to create a custom version of UserControl to implement some standard animations for views when loading.
But when I add a ContentPresenter I'm not able to add content to my control. Why though?
Here is the Template I use for my custom control.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:EzNintendo.Desktop.Controls">
<Style TargetType="{x:Type local:AnimatedView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:AnimatedView}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
and the default code for a custom control
public class AnimatedView : Control
{
static AnimatedView()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(AnimatedView),
new FrameworkPropertyMetadata(typeof(AnimatedView)));
}
}
and
and that is how I try to use it.
<controls:AnimatedView x:Class="MyView"
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:controls="clr-namespace:MControls;assembly=MControls">
<Grid>
<TextBlock Text="Hello World!" />
</Grid>
</controls:AnimatedView>
When I remove the Grid it works just fine.
Related
I am creating a split button where I am trying to set a default template to it so if the split button is to be used elsewhere outside of the control, it can be. The issue here is, is that when a user calls the split button into their control and they attach their style to it, it completely removes everything from the split button. I'm not entirely sure how to fix it. I would appreciate any help.
MySplitButton.xaml:
<local:SplitButton x:Class="WpfApp4.SplitButton.MySplitButton"
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:WpfApp4.SplitButton"
mc:Ignorable="d"
d:DesignHeight="25" d:DesignWidth="100">
<local:SplitButton.Resources>
</local:SplitButton.Resources>
<local:SplitButton.Style>
<Style TargetType="{x:Type local:SplitButton}" BasedOn="{StaticResource {x:Type ToggleButton}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:SplitButton}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="25"/>
</Grid.ColumnDefinitions>
<local:LockableToggleButton Grid.Column="0">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="True"/>
</local:LockableToggleButton>
<Button Grid.Column="1"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</local:SplitButton.Style>
</local:SplitButton>
MySplitButton.xaml.cs
public partial class MySplitButton : SplitButton
{
public MySplitButton()
{
InitializeComponent();
}
}
public class SplitButton : ToggleButton
{
public ICommand PrimaryButtonCommand
{
get { return (ICommand)GetValue(PrimaryButtonCommandProperty); }
set { SetValue(PrimaryButtonCommandProperty, value); }
}
public static readonly DependencyProperty PrimaryButtonCommandProperty;
public bool ToggleLock
{
get { return (bool)GetValue(ToggleLockProperty); }
set { SetValue(ToggleLockProperty, value); }
}
public static readonly DependencyProperty ToggleLockProperty;
public bool ContextMenuOpen
{
get { return (bool)GetValue(ContextMenuOpenProperty); }
set { SetValue(ContextMenuOpenProperty, value); }
}
public static readonly DependencyProperty ContextMenuOpenProperty;
static SplitButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(SplitButton), new FrameworkPropertyMetadata(typeof(SplitButton)));
PrimaryButtonCommandProperty = DependencyProperty.Register("PrimaryButtonCommand", typeof(ICommand), typeof(SplitButton), new FrameworkPropertyMetadata(null));
ToggleLockProperty = DependencyProperty.Register("ToggleLock", typeof(bool), typeof(SplitButton), new UIPropertyMetadata(false));
ContextMenuOpenProperty = DependencyProperty.Register("ContextMenuOpen", typeof(bool), typeof(SplitButton), new FrameworkPropertyMetadata(false));
}
}
public class LockableToggleButton : ToggleButton
{
public bool ToggleLock
{
get { return (bool)GetValue(ToggleLockProperty); }
set { SetValue(ToggleLockProperty, value); }
}
public static readonly DependencyProperty ToggleLockProperty =
DependencyProperty.Register("ToggleLock", typeof(bool), typeof(LockableToggleButton), new UIPropertyMetadata(false));
protected override void OnToggle()
{
if (!ToggleLock)
{
base.OnToggle();
}
}
}
So when I call MySplitButton on MainWindow like this, and attach a style to it, everything gets overridden and I don't know what I am doing wrong:
<Window x:Class="WpfApp4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp4"
xmlns:cc="clr-namespace:WpfApp4.SplitButton"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.CommandBindings>
<CommandBinding Command="{x:Static local:MainWindow.PrimaryButtonUICommand}" Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
<Window.Resources>
<Style x:Key="thisStyle" TargetType="{x:Type cc:SplitButton}">
<Setter Property="Background" Value="Yellow"/>
</Style>
</Window.Resources>
<Grid>
<cc:MySplitButton x:Name="SplitButton" Margin="346,197,345,188" Style="{DynamicResource thisStyle}">
<StackPanel Orientation="Horizontal">
<Label Content="hello"/>
</StackPanel>
</cc:MySplitButton>
</Grid>
</Window>
The way that you created the XAML markup for your custom button, the style will get instantiated and applied to a MySplitButton instance when it is created. Specifying a TargetType on a style does not automatically inherit the default style. You can base a style on another using the BasedOn attribute. However, you cannot reference your default style, since it is only available on an instance of MySplitButton. The solution is to extract the default style to a resource dictionary to share it.
Usually, when creating custom controls, you would create a dedicated assembly and create a resource dictionary called Generic.xaml in a Themes folder. This resource dictionary contains your default control styles. Note that the TargetType is MySplitButton, because that is your custom control, not SplitButton. Since there is no x:Key, this style is implicit and will be applied to all MySplitButton controls in scope automatically.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyControlLibrary">
<!-- Default style for your split button -->
<Style TargetType="{x:Type local:MySplitButton}" BasedOn="{StaticResource {x:Type ToggleButton}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MySplitButton}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="25"/>
</Grid.ColumnDefinitions>
<local:LockableToggleButton Grid.Column="0">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="True"/>
</local:LockableToggleButton>
<Button Grid.Column="1"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ...styles, templates and resources for other controls. -->
</ResourceDictionary>
In other projects you have to include the resources in the application resources, or at least in any resource dictionary in a scope where you use the controls. Otherwise, the style cannot be resolved.
<Application x:Class="MyApplication"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MyControlLibrary;component/Themes/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Specifying a TargetType does not automatically inherit a style of a control.
Gets or sets the type for which this style is intended.
In order to base one style on another, you have to specify the base style through the BasedOn attribute.
Gets or sets a defined style that is the basis of the current style. [...] When you use this property, the new style will inherit the values of the original style that are not explicitly redefined in the new style.
Consequently, you have to adapt your new thisStyle like below.
<Style x:Key="thisStyle" TargetType="{x:Type cc:MySplitButton}" BasedOn="{StaticResource {x:Type cc:MySplitButton}}">
<Setter Property="Background" Value="Yellow"/>
</Style>
Remember, your original SplitButton style must be available in the current scope, so your users must make sure to include the corresponding resource dictionary in their library or application.
Try to use BasedOn.
<Window.Resources>
<Style x:Key="thisStyle" TargetType="{x:Type cc:SplitButton}" BasedOn="{StaticResource {x:Type cc:SplitButton}}">
<Setter Property="Background" Value="Yellow"/>
</Style>
</Window.Resources>
I have a PerformanceMeterStyle.xaml with one property that set's the background to yellow:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:TemplateLearn.Controls">
<Style TargetType="controls:PerformanceMeter" x:Key="PerformanceMeterStyle">
<Setter Property="Background" Value="Yellow"/>
</Style>
</ResourceDictionary>
Then I have PerformanceMeter.cs where my dependency property's will come in. For know it just derives from Control:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace TemplateLearn.Controls
{
public class PerformanceMeter : Control
{
}
}
In my MainWindow.xaml i use my created control:
<Window x:Class="TemplateLearn.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TemplateLearn"
xmlns:controls="clr-namespace:TemplateLearn.Controls"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<ResourceDictionary Source="Theme/Styles/PerformanceMeterStyle.xaml" />
</Window.Resources>
<controls:PerformanceMeter Style="{StaticResource PerformanceMeterStyle}"/>
</Window>
Why is the background color of my control not changing to the property I set in PerformanceMeterStyle.xaml?
you should create control template for that as follows:
<Style TargetType="controls:PerformanceMeter" x:Key="PerformanceMeterStyle">
<Setter Property="Background" Value="Yellow" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:PerformanceMeter}">
<Border x:Name="border"
Background="{TemplateBinding Background}">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This might actually work, if not let me know.
I've got a custom UserControl that I try to add to another UserControl:
<UserControl x:Class="MyProject.Screens.Test"
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:MyProject.Screens"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Button Style="{StaticResource TestStyle}"/>
</Grid>
<UserControl.Resources>
<Style x:Key="TestStyle" TargetType="{x:Type Button}">
<Setter Property="Padding" Value="1"/>
</Style>
</UserControl.Resources>
It looks ok in design window, and the projects compiles fine. But if I try to add this UserControl to another UserControl:
<UserControl x:Class="MyProject.Screens.MainScreen"
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:MyProject.Screens"
mc:Ignorable="d"
d:DesignHeight="1080" d:DesignWidth="1920">
<Grid>
<local:Test/>
</Grid>
</UserControl>
I recieve an error:
Cannot locate resource "TestStyle"
in MainScreen.
What am I doing wrong?
Put the Resources declaration before the Content:
<UserControl ...>
<UserControl.Resources>
<Style x:Key="TestStyle" TargetType="{x:Type Button}">
<Setter Property="Padding" Value="1"/>
</Style>
</UserControl.Resources>
<Grid>
<Button Style="{StaticResource TestStyle}"/>
</Grid>
</UserControl>
I have an application with a large number of styles that are currently duplicated in the .xaml for each window of the application. I would like to be able to reference one file called UiStyles.xaml that contains all of the styles for the application.
After reading a ton of answered questions on here and Google I've tried this:
ButtonStyle.xaml:
<Style TargetType="{x:Type Button}" x:Key="ButtonStyle">
<Setter Property="Background" Value="Red"/>
<Setter Property="FontSize" Value="48"/>
</Style>
</ResourceDictionary>
UiStyles.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ButtonStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="Control" /> <!-- Added this based on other user's suggestions to account for .net 4 bug -->
</ResourceDictionary>
MainWindow.xaml:
<Window x:Class="TestingGround.UI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary Source="Resources/UIStyles.xaml"/>
</Window.Resources>
<Grid>
<Button Click="ButtonBase_OnClick" Content="Test Text"/>
</Grid>
</Window>
But my button style is not being applied! What am I doing wrong?
Note when you apply a key to a style, you have to explicitly apply it to the control so
<Button Click="ButtonBase_OnClick"
Content="Test Text"
Style={StaticResource ButtonStyle} />
However if you want all buttons to default to the style remove the x:key="ButtonStyle".
<Style TargetType="...">
You have created your button style with an x:Key, but are not referencing that in your button instance.
You need to set the "Style" property of the button like so:
<Button Click="ButtonBase_OnClick" Style="{StaticResource ButtonStyle}" Content="Test Text"/>
I'm totally new on WPF and I need your help for creating a wpf custom ListBox with scrollbar wider than the default.
I've found a solution that works fine for a Window WPF including a ListBox:
<Window x:Class="iFixCustomControlsTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cc="clr-namespace:iFixCustomControls;assembly=iFixCustomControls"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox HorizontalAlignment="Left" Height="92" Margin="56,88,0,0" VerticalAlignment="Top" Width="357" ScrollViewer.VerticalScrollBarVisibility="Visible"/>
</Grid>
<Window.Resources>
<Style TargetType="ScrollBar">
<Setter Property="Width" Value="100"/>
</Style>
</Window.Resources>
</Window>
This solution is not the my favorite one, because it implies to write code in a Window including a "classic" Listbox. What I need is a way to modify scrollbar inside the Listbox (if I understood fine) in Generic.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:iFixCustomControls">
<Style TargetType="local:iFixCustomListBox" BasedOn="{StaticResource {x:Type ListBox}}">
<!--
Setting scrollbar wider than default
Something like:
<Style TargetType="ScrollBar">
<Setter Property="Width" Value="100"/>
</Style>
-->
</Style>
</ResourceDictionary>
.cs file is:
public class iFixCustomListBox : ListBox
{
static iFixCustomListBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(iFixCustomListBox), new FrameworkPropertyMetadata(typeof(iFixCustomListBox)));
}
}
Is this approach correct or a better way should involve User Control instead Custom Controls?
If I understand you correctly you have a custom control type derived from ListBox and you want every instance of that control to have a wider vertical scrollbar.
If so, you can just use a custom style for your control (which you probably have already), and add a ScrollBar style to that style's Resources collection:
<Style TargetType="{x:Type local:iFixCustomListBox}">
<Style.Resources>
<Style TargetType="{x:Type ScrollBar}">
<Setter Property="Width" Value="100" />
</Style>
</Style.Resources>
</Style>
I tried with this style placed in the resources collection of (a) a window, and (b) the application, and it worked fine in both cases, so I assume it would also work if placed in generic.xaml.
What about this?
<ScrollViewer Width="100">
<ListBox ...>
</ScrollViewer>