I'm trying to develop a custom tri-state button user control and so far I've been using CTF to set properties.
But I would like to change this to be using the WPF property system with PropertiesDependencies.
Unfortunately I don't manage to make it work, when I set the property from my xaml (father) using a DynamicResource, the value is not set.
<common:StateImageButton x:Name="story_buttonRecord" BackTest="{DynamicResource backTest}" />
Here is the code I have in my button controller :
public ImageSource BackTest
{
get { return (ImageSource)this.GetValue(BackProp); }
set { this.SetValue(WidthProp,value); }
}
public static readonly DependencyProperty BackProp =
DependencyProperty.Register(
"BackTest",
typeof(ImageSource),
typeof(StateImageButton),
new FrameworkPropertyMetadata());
I don't even use the property in my button xaml yet, but it apparently doesn't even enter in the Setter. I've been searching a lot online without success. So maybe I'm missing something .
Thanks in advance for your help,
Boris
Also, WPF doesn't use the setter provided to set a property, it does it directly.
The way to debug when WPF sets a property is to add a callback for when the property is set, like so.
public static readonly DependencyProperty BackProp =
DependencyProperty.Register(
"BackTest",
typeof(ImageSource),
typeof(StateImageButton),
new FrameworkPropertyMetadata(OnBackChanged));
private static void OnBackChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var sender = (StateImageButton)d; // Put a breakpoint here
}
Related
I created a user control and wanted to get the value of the DependencyProperty "ListBoxReadOnly" in the code. I set the value in the XAML:
<control:AutoCompleteTextBox x:Name="actbFullName" ListBoxReadOnly="True"/>
When I tried to read the value in the constructor, it only shows the default value which is false.
I tried to get the value via a callback back but probably I am lacking some understanding of the whole framework. Since the callback is a static method, I cannot apply it to the instance of my user control.
public static readonly DependencyProperty ListBoxReadOnlyDependency =
DependencyProperty.Register("ListBoxReadOnly", typeof(bool),
typeof(AutoCompleteTextBox), FrameworkPropertyMetadata
(false, FrameworkPropertyMetadataOptions.AffectsRender));
public bool ListBoxReadOnly
{
get
{
return (bool) GetValue(ListBoxReadOnlyDependency);
}
set
{
SetValue(ListBoxReadOnlyDependency, value);
}
}
// constructor of user control
public AutoCompleteTextBox()
{
InitializeComponent();
// *** shows "false" (default value) even though set to true in XAML
// *** see XAML above ***
var test = ListBoxReadOnly;
}
Any help is appreciated :-)
I would expect your code (as is) to show false. The DP is initialized to false. In the constructor of your control, neither the default control style, nor the properties set in xaml have been applied yet.
The style is only applied after OnApplyTemplate() is called (unless you force it).
If you want to track DP changes, you need a DP change handler.
When I tried to read the value in the constructor, it only shows the default value which is false.
The property can't be set before the control has been initialized.
Since the callback is a static method, I cannot apply it to the instance of my user control.
You could cast the DependencyObject to the type of your control in the callback:
public static readonly DependencyProperty ListBoxReadOnlyDependency =
DependencyProperty.Register("ListBoxReadOnly", typeof(bool),
typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata
(false, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnChanged)));
private static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
AutoCompleteTextBox ctrl = (AutoCompleteTextBox)d;
var x = ctrl.ListBoxReadOnly;
//...
}
Ok, so I'm trying to run some code that modifies a UI when a user changes a custom control's dependency property value in design mode; but only when in design mode.
I've tried these approaches:
1.
public static DependencyProperty x = ...Register(..., new PropertyMetadata(null, changeMethod));
2.
set { SetValue(XProp, value); changeMethod(value); }
3.
var observable = x as INotifyPropertyChanged;
observable.PropertyChanged += ObservablePropertyChanged;
But all of them seem to have their own issues in that they either trigger errors or don't work at all.
So does anyone know what the correct way to listen to a dependency property change in design mode is, and if so can you give an example?
The right way to handle DependencyProperty changes is to:
. Declare the DependencyProperty:
public static DependencyProperty MyXProperty;
. Create the public get/set Property:
public string MyX
{
get { return (string)GetValue(MyXProperty); } //Supposing that the property type is string
set { SetValue(MyXProperty, value); }
}
. Register the DependencyProperty in your static constructor:
static MyClass()
{
MyXProperty= DependencyProperty.Register("MyX", typeof(string), typeof(MyClass), new FrameworkPropertyMetadata("", OnMyXPropertyChanged));
}
. Declare the Property Changed Method:
private static void OnMyXPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MyClass thisClass = d as MyClass ;
//Do Something
}
Please provide more information if you still can't find your solution.
I am trying to register an WPF attached property on a grid control, however, I met very strange behavior today:
public static class MyClass
{
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.RegisterAttached("MyProperty", typeof(string),
typeof(MyClass), null);
public static string GetMyProperty(DependencyObject d)
{
return (string)d.GetValue(MyPropertyProperty);
}
public static void SetMyProperty(DependencyObject d, string value)
{
d.SetValue(MyPropertyProperty, value); //<-- set breakpoint here
}
}
XAML:
<GridControl local:MyClass.MyProperty="My Name">
...
</GridControl>
when I wrote like this, the attached property's setter never gets executed. and value never be set. but I can snoop into the grid and found the attached property is attached with an empty value.
but when I change the attached property name to:
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.RegisterAttached("xxxMyProperty", typeof(string),
typeof(MyClass), null);
i.e. use a different name other than MyProperty. then the breakpoint can be hit! and value can be set!
Moreover, when I change the attached property as:
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.RegisterAttached("MyProperty", typeof(string),
typeof(UIElement), null);
i.e. change the owner type to UIElement, then I can also hit the breakpoint, just wondering why?
However, when I setup a binding in XAML instead of a string constant, each case above will got an exception saying A 'Binding' can only be set on a DependencyProperty of a DependencyObject
Binding XAML example:
<GridControl local:MyClass.MyProperty="{Binding MyStringValue}">
...
</GridControl>
Does anyone met this strange behavior before? What am I missing in my case? Thanks in advance for the reply!
If you are referring to the SetMyProperty method as the 'setter', then you should know that these methods are simply 'helper' methods for you to use. The Framework does not generally use these methods.
If however, you are saying that you would like to know when the value changes, then there is another way of doing this. Add a PropertyChangedCallback handler to the declaration of the property:
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.RegisterAttached("MyProperty", typeof(string), typeof(MyClass),
new UIPropertyMetadata(default(string.Empty), OnMyPropertyChanged));
public static void OnMyPropertyChanged(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs e)
{
string myPropertyValue = e.NewValue as string;
}
I have created a user control in WPF, and in the code behind I have created some dependency properties.
I added several WPF controls to my user control, one of the is a progress bar, so What I tried to do is to expose the Value progressBar property as below:
public static readonly DependencyProperty valueProperty = DependencyProperty.Register(
"Value",
typeof(Double),
typeof(MyUserControl),
new FrameworkPropertyMetadata(
ValuePropertyCallback));
private static void ValuePropertyCallback(DependencyObject controlInstance, DependencyPropertyChangedEventArgs args)
{
MyUserControl myUserControlInstance = (ProgressControl)controlInstance;
myUserControlInstance.progressBar.Value = (Double)args.NewValue;
}
public Double Value
{
get { return (Double)GetValue(valueProperty); }
set { SetValue(valueProperty, value); }
}
And in XAML I have written this:
<MyUserControl Name="myControl" Value="{Binding ProgressBarValue}" >
But It seems not to be working, neither setting nor getting the value.
I have a couple hours reviewing this but I cant realize what I am doing wrong.
Hope you can help me, Thank you in advance.
(Note: DataContext are defined previously and it is correct since this is the only binding that does not work)
valueProperty <----> "Value" does not match... (v/V) :=)
Have you tried Mode=TwoWay:
<MyUserControl Name="myControl" Value="{Binding ProgressBarValue, Mode=TwoWay}" >
I have also used PropertyMetadata instead of FrameworkPropertyMetadata
Try changing the name of your dependency property to be PascalCased:
ValueProperty
You might also want to look at BindsTwoWayByDefault to make sure changes to your DP are written to the source object.
Turns out that my problem was that I didnt implement the INotifyPropertyChanged interface, so, the changes I did were not showed. But since I am new at WPF using MVVM I didnt know that.
But you just need to create an ObservableObject, then your viewModel class has to inherit from it.
Here is an example to create the ObservableObject class and how to inherit from it.
I have a highly customized Edit control which inherits RichTextBox. I needed a way to bind a Value to this control, so I registered a new DependencyProperty, but I have trouble to code it like I need.
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(string), typeof(XliffRichCellEditor),
new PropertyMetadata(new PropertyChangedCallback(XliffRichCellEditor.OnValuePropertyChanged)));
public String Value
{
get { return (String)this.GetValue(ValueProperty); }
set { this.SetValue(ValueProperty, value); }
}
private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Need to change Document in RichTextBox when Binding Source is changed
// But also ignore if the change comes from RichTextBox which is only updating
// the DependencyProperty. In this case Binding Source should be updated.
}
Please help.
use can use UpdateSourceTrigger=Explicit in your Binding statement and get the control of property updation in your hand.
Check this Thread