Unable to set style-trigger property to custom dependency property - c#

I got another problem while working with my usercontrol's xaml file -.-'
I tried to implement an IsChecked property to my custom button in order to set a different background colour if the button is checked.
So I created a DependencyProperty like this:
public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register("IsChecked", typeof(bool), typeof(LeftMenuBtn));
public bool IsChecked
{
get { return (bool)GetValue(IsCheckedProperty); }
set { SetValue(IsCheckedProperty, value); }
}
Then I setup a new style trigger to handle this property:
<Style x:Key="ButtonEnableStates" TargetType="{x:Type Grid}">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="{DynamicResource CheckedStateGradient}" />
</Trigger>
</Style.Triggers>
</Style>
Expression Blend now underlines Property="IsChecked" and says:
The member "IsChecked" is not recognized or is not accessible.
How can I solve this problem?

Well, the Style's TargetType is Grid and the property is defined for LeftMenuBtn, not going to work like that.

Related

XDG0008 error occuring while implementing DependencyProperty into TemplateBinding [duplicate]

This question already has answers here:
Template Binding with Attached Properties
(2 answers)
Closed 1 year ago.
To easily change the template-specific brushes of a button without directly changing the template, I decided to make a DependencyProperty that will bind to a template-specific brush. That way, I can change this brush just as easy as changing any other regular property. However, after implementing this DependencyProperty, I encountered an error: "Name "ExtensionClass" does not exist in namespace "clr-namespace:extensions"." What causes this error?
XAML:
<ResourceDictionary xmlns:ext="clr-namespace:Extensions"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<ControlTemplate x:Key="ButtonBaseControlTemplate1" TargetType="{x:Type ButtonBase}">
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="border" Value="{TemplateBinding Property=ext:ExtensionsClass.MouseOverBackground}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ResourceDictionary>
C#:
namespace Extensions {
public class ExtensionsClass {
public static readonly DependencyProperty MouseOverBackgroundProperty = DependencyProperty.Register("MouseOverBackground", typeof(Brush), typeof(Button));
public static void SetMouseOverBackground(UIElement element, Brush value) {
element.SetValue(MouseOverBackgroundProperty, value);
}
public static Brush GetMouseOverBackground(UIElement element) {
return (Brush)element.GetValue(MouseOverBackgroundProperty);
}
}
}
In addition to the problem with the Binding, which is covered in the answer to the duplicate question, you also have to be aware that you are declaring an attached property, which has to be registered with the RegisterAttached method.
Besides that, in both the Register and the RegisterAttached methods, the third argument has to be the type that declares the property, not the type of element where you intend to set the property, i.e. typeof(ExtensionsClass) here.
public static class ExtensionsClass
{
public static readonly DependencyProperty MouseOverBackgroundProperty =
DependencyProperty.RegisterAttached(
"MouseOverBackground",
typeof(Brush),
typeof(ExtensionsClass),
null);
public static void SetMouseOverBackground(UIElement element, Brush value)
{
element.SetValue(MouseOverBackgroundProperty, value);
}
public static Brush GetMouseOverBackground(UIElement element)
{
return (Brush)element.GetValue(MouseOverBackgroundProperty);
}
}
You bind to an attached property by means of a Binding Path with parentheses:
<Setter
Property="Background"
TargetName="border"
Value="{Binding Path=(ext:ExtensionsClass.MouseOverBackground),
RelativeSource={RelativeSource TemplatedParent}}"/>

Change Property by a Behavior disable Trigger in XAML Style

Below you can se a part of my Behavior and XAML Style. So if no Behavior is attached, everything is fine. But with the attached Behavior the Trigger is not fired anymore and I only have this new Color on my background. Someone can give me a tip, how to change the Color without overriding the Trigger?
Behavior Snippet
public class ChangeColor : Behavior<FrameworkElement>
{
public string NewColor
{
get { return (string)GetValue(NewColorProperty); }
set { SetValue(NewColorProperty, value); }
}
public static DependencyProperty NewColorProperty = DependencyProperty.Register("NewColor", typeof(string), typeof(ChangeColor), new PropertyMetadata(""));
protected override void OnAttached()
{
if (!DesignerProperties.GetIsInDesignMode(this))
{
AssociatedObject.Loaded += AssociatedObject_Loaded;
}
}
public Brush DefaultColor
{
get { return (Brush)GetValue(DefaultColorProperty); }
set { SetValue(DefaultColorProperty, value); }
}
public static DependencyProperty DefaultColorProperty = DependencyProperty.Register("DefaultColor", typeof(Brush), typeof(ChangeColor), null);
private PropertyInfo _TargetProperty;
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
_TargetProperty = AssociatedObject.GetType().GetProperty("Background");
if (DefaultColor == null)
{
try
{
DefaultColor = (Brush)_TargetProperty.GetGetMethod().Invoke(AssociatedObject, null);
}
catch
{
//ignore
}
}
}
private void ChangeTheColor()
{
if ((bool)change)
{
_TargetProperty.GetSetMethod().Invoke(AssociatedObject, new object[] { NewColor });
}
else
{
_TargetProperty.GetSetMethod().Invoke(AssociatedObject, new object[] { DefaultColor });
}
}
}
XAML Snippet
<Style TargetType="Controls:CustomButton">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsReadOnly" Value="False"/>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Background" Value="{Extensions:ThemeColors KeyCode=BackgroundSpecialColor}"/>
</MultiTrigger.Setters>
</MultiTrigger>
</Style.Triggers>
</Style>
Try to make DependencyProperty like this.
public Brush NewColor
{
get { return (Brush)GetValue(NewColorProperty); }
set { SetValue(NewColorProperty , value); }
}
public static readonly DependencyProperty NewColorProperty =
DependencyProperty.Register("NewColor" , typeof(Brush) ,
typeof(ChangeColor) ,
new FrameworkPropertyMetadata(new SolidColorBrush(Colors.Black) ,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
where SolidColorBrush(Colors.Black) is default color, and this set it to bind TwoWay by default FrameworkPropertyMetadataOptions.BindsTwoWayByDefault),maybe that was a problem, becouse if you dont set it there to bind TwoWay by default then you have to make that in binding Mode=TwoWay, or else your Property wont register that change. Hope that will help you.ΒΈ
EDIT: As i can see you are using Button as base class and want to change button background on trigger? I really can't say what is the best way to do it, but i would do it in generic.xaml,a and in <ControlTemplate.Triggers> i would do it like this:
<ControlTemplate.Triggers>
<Trigger Property="IsPressed"
Value="true">
<Setter Property="Background"
Value="{Binding NewColor, RelativeSource={RelativeSource TemplatedParent}}" />
</Trigger>
</ControlTemplate.Triggers>
And Up in beggining of your style you have something like this:
<Setter Property="Background"
Value="{Binding BorderBrush, RelativeSource={RelativeSource TemplatedParent}}" />
just change that line of code to this:
<Setter Property="Background"
Value="{Binding DefaultColor, RelativeSource={RelativeSource TemplatedParent}}" />
That way you have set your Default color in the begining, and your NewColor on Trigger.
and when you call that custom button in some xaml code
<Grid>
<customButton:Button DefaultColor="set your default color"
NewColor="Set your onClick color".../>

Setting A dependency property by this

I've created a type of Border called SelectableBorder that has an additional property called "IsSelected". I'm using this property in some triggers e.g.:
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True" />
<Condition Property="IsMouseOver" Value="True" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Background" Value="{DynamicResource AccentColorBrush3}" />
</MultiTrigger.Setters>
However in the code in the background there is no way for me to set IsSelected, How do I go about creating a property that can be used in xaml triggers and in code in the background?
This is the current SelectableBorder code
public class SelectableBorder : Border
{
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.RegisterAttached("IsSelected", typeof(bool), typeof(Border), new PropertyMetadata(false));
public static void SetIsSelected(UIElement element, bool value)
{
element.SetValue(IsSelectedProperty, value);
}
public static bool GetIsSelected(UIElement element)
{
return (bool)element.GetValue(IsSelectedProperty);
}
}
I am also seeing:
'SelectableBorder' initialization failed: The type initializer for 'SelectableBorder' threw an exception.
Which suggests to me that I'm not doing that well at my first attempt. Could you please guide me in the correct direction to solving these problems?
Since you're adding property to DependencyObject so you can use normal DependencyProperty instead of attached one. You can use attached if you want but then trigger should change. Also owner type of your property should be SelectableBorder instead of Border. You can also add IsSelected CLR wrapper do make it easier to set/get value in code behind.
public class SelectableBorder : Border
{
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(SelectableBorder), new PropertyMetadata(false));
public bool IsSelected
{
get { return (bool)GetValue(IsSelectedProperty); }
set { SetValue(IsSelectedProperty, value); }
}
}

XAML How to own StaticResource in derived UserControl class

I have the following problem. I have a class which derives from UserControl, here is the code:
public partial class MyUC : UserControl
{
[...]
public bool IsFlying { get { return true; } }
[...]
}
I want to use a style, which is created for the class MyUC, below is the style code. It is located in App.Xaml :
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dc="clr-namespace:MyNamespace"
<Application.Resources>
<Style x:Key="mystyle" TargetType="dc:MyUC ">
<Style.Triggers>
<Trigger Property="IsFlying" Value="true">
<Setter Property = "Background" Value="Blue"/>
</Trigger>
</Style.Triggers>
</Style>
</Application.Resources>
As you can see I want to use a property which I declared in MyUC.
The problem is that when I am trying to add a style to my control, an error occurres.
<UserControl x:Class="MyNamespace.MyUC"
[...]
Style="{StaticResource mystyle}">
<UserControl.Resources>
</UserControl.Resources>
</UserControl>
The error is: 'MyUC' TargetType does not match type of element 'UserControl'.
As far as I understand, the compiler do not recognize class MyUC to be derived from UserControl. How to fix it?
Thanks in advance!
Error might be at design time only, it should work fine at runtime. Run your app and see if it works for you.
Moreover your trigger won't work for normal CLR property, you need to make it a Dependency Property -
public bool IsFlying
{
get { return (bool)GetValue(IsFlyingProperty); }
set { SetValue(IsFlyingProperty, value); }
}
public static readonly DependencyProperty IsFlyingProperty =
DependencyProperty.Register("IsFlying", typeof(bool),
typeof(SampleUserControl), new UIPropertyMetadata(true));
Also, you can remove the x:Key="mystyle" from your style declaration. It will automatically gets applied to your UserControl.
That way you won't have to explicitly set style on your UserControl. This line won't be required then - Style="{StaticResource mystyle}"

Updating Custom Attached Property in Style Trigger with Setter

I was trying out attached properties and style triggers hoping to learn more about it.
I wrote a very simple WPF windows app with an attached property:
public static readonly DependencyProperty SomethingProperty =
DependencyProperty.RegisterAttached(
"Something",
typeof(int),
typeof(Window1),
new UIPropertyMetadata(0));
public int GetSomethingProperty(DependencyObject d)
{
return (int)d.GetValue(SomethingProperty);
}
public void SetSomethingProperty(DependencyObject d, int value)
{
d.SetValue(SomethingProperty, value);
}
And I was trying to update the 'Something' attached property with a property trigger defined in the button style section:
<Window x:Class="TestStyleTrigger.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestStyleTrigger;assembly=TestStyleTrigger"
Title="Window1" Height="210" Width="190">
<Window.Resources>
<Style x:Key="buttonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="local:Window1.Something" Value="1" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Button Style="{StaticResource buttonStyle}"></Button>
</Window>
However, I kept getting following compilation error:
error MC4003: Cannot resolve the Style Property 'Something'. Verify that the owning type is the Style's TargetType, or use Class.Property syntax to specify the Property. Line 10 Position 29.
I can't understand why it gives me this error because I did use the 'Class.Property' syntax in the tag of the section. Can any one tell me how can I fix this compilation error?
Your backing methods for the dependency property are named incorrectly and must be static:
public static int GetSomething(DependencyObject d)
{
return (int)d.GetValue(SomethingProperty);
}
public static void SetSomething(DependencyObject d, int value)
{
d.SetValue(SomethingProperty, value);
}
Also, you shouldn't specify the assembly in the local XML NS mapping in the XAML because the namespace is in the current assembly. Do this instead:
xmlns:local="clr-namespace:TestStyleTrigger"

Categories