Where this is the clr way of writing a property:
public byte Value
{
get{
return GetByteData();
}
set{
SetByteData(value);
}
}
I've read up on how to do the same the dependency property way, and this is all I could do by myself:
public byte Value
{
get { return (byte)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value", typeof(byte), typeof(MyControl),
new FrameworkPropertyMetadata((byte)0, ValueChanged));
public static void ValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
byte r = (byte)e.NewValue;
MyControl v = (MyControl)d;
v.SetByteData(r);
}
With the examples I've looked at, from which I've made the above snippet, I can't find a place to put the GetByteData(), which calculates an output value for the current UI-state when the user interacts, so as to update the 'Value'.
Until previously I was putting it in the getter anyway like with clr, but I get the feeling that it's the wrong approach, but I could be wrong. Where should I be putting it? If not, what should be my approach? Is it at all possible to have a programmatic getter for a dependency property?
It's possible that I've been using the wrong keywords to look for a solution. Any help putting me in the right direction would be much appreciated. Thanks in advance.
As long as it is only the source (and not the target) property of a Binding, as in
{Binding Value, ElementName=MyControlName}
and you don't want to apply a value by a Style Setter, or animate the value, the property does not need to be a dependency property.
Just implement INotifyPropertyChanged like this:
public partial class MyControl : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public byte Value
{
get { return GetByteData(); }
set
{
SetByteData(value);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value)));
}
}
...
}
Related
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 have a usercontrol with a dependency property.
public sealed partial class PenMenu : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public bool ExpandCollapse
{
get
{
return false;
}
set
{
//code
}
}
public static readonly DependencyProperty ExpandCollapseProperty = DependencyProperty.Register("ExpandCollapse", typeof(bool), typeof(PenMenu), null);
//some more code
}
And I am assigning value in XAML page as:
<Controls:PenMenu x:Name="penMenu" Opened="Menu_Opened"
ExpandCollapse="{Binding PenMenuVisible}" />
But it is not hitting GET-SET part of ExpandCollapse property in the usercontrol.
So I added bool to bool converter just to check what value is being passed with binding like:
<Controls:PenMenu x:Name="penMenu" Opened="Menu_Opened"
ExpandCollapse="{Binding PenMenuVisible, Converter={StaticResource booleanToBooleanConverter}}" />
And with breakpoint in Converter, I see the value being passed is correct.
What is the possible reason it's not assigned to the Dependency Property?
Also in XAML page if I say:
<Controls:PenMenu x:Name="penMenu" Opened="Menu_Opened"
ExpandCollapse="true"/>
then it hits the GET-SET part of ExpandCollapse property in the usercontrol.
I am stuck. This is weird. Please help.
It's frustrating isn't it? First, include a changed event handler. Like this:
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string),
typeof(MyControl), new PropertyMetadata(string.Empty, Changed));
private static void Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var c = d as MyControl;
// now, do something
}
Then, please read this article so you see there are more gotchas than just that one: http://blog.jerrynixon.com/2013/07/solved-two-way-binding-inside-user.html
Best of luck!
The getter and setter of a dependency property are not guaranteed to be run, and in particular the WPF binding engine / XAML processor is documented to bypass these. Have a look on MSDN - the getter/setter should just be a wrapper around GetValue/SetValue on the DependencyProperty itself.
Instead of reacting in the setter of your property, you should add a property changed handler in the original call to DependencyProperty.Register, when you can act on the new value.
(see other questions).
I tried this out just to see what will happen and it did work but I have no idea why so. Can somebody explain me what is happening in the background of DependencyProperties?
I have a class which declares a DependencyProperty but then in another class I target that DependencyProperty by using GetValue and SetValue.
Here is an example:
public class DependencyProperties : DependencyObject
{
public Size EstimatedSize
{
get { return (Size)GetValue(EstimatedSizeProperty); }
set { SetValue(EstimatedSizeProperty, value); }
}
public static readonly DependencyProperty EstimatedSizeProperty =
DependencyProperty.Register("EstimatedSize", typeof(Size), typeof(DependencyProperties), null);
}
public class MyControl: ContentControl
{
public Size CalculatedSize
{
get { return (Size)GetValue(DependencyProperties.EstimatedSizeProperty); }
set { SetValue(DependencyProperties.EstimatedSizeProperty, value); }
}
protected override OnApplyTemplate()
{
// This works but why? How is it possible to do this? What is happening under the hood?
this.CalculatedSize = new Size(123, 123);
}
}
Why is it possible to do this? What is happening in the background of this example? The MyControl class didnt register the DP but it can use it. Can somebody tell me what is happening under the hood?
I googled the image that I'd like to show you.
See the link below, and the concept of DP is well documented.
http://www.abhisheksur.com/2011/07/internals-of-dependency-property-in-wpf.html
And, let's go to the bottom-line directly, when you invite and use MyControl in your app, contained DP is automatically registered.
This is why DP is use static prefix. For the reason of static readonly in DP declaration, kindly read https://stackoverflow.com/a/5610015/361100 link (Priyank's quoted answer).
I've created a dependency property like this:
public partial class MyControl: UserControl
{
//...
public static DependencyProperty XyzProperty = DependencyProperty.Register("Xyz",typeof (string),typeof (MyControl),new PropertyMetadata(default(string)));
public string Xyz
{
get { return (string) GetValue(XyzProperty ); }
set { SetValue(XyzProperty , value); }
}
//...
}
Then bind it to my wpf window and everything worked fine.
When I tried to add some logic to the setter I notice it wasn't being called. I modify the get;Set up to a point now they look like this:
get{return null;}
set{}
And it is still works! How come? What's the use of that GetValue/SetValue calls?
The WPF data binding infrastructure uses the DependencyProperty directly, the Xyz property is a convenience interface for the programmer.
Take a look at the PropertyMetadata in the call to DependencyProperty.Register, you can supply a callback that will run when the property value is changed, this is where you can apply your business logic.
The DependencyProperty is the backing store for the XyzProperty. If you access the property through the DependencyProperty interface, it completely bypasses the Property's Get/Set accessor.
Think of it this way:
private int _myValue = 0;
public int MyValue
{
get { return _myValue; }
set { _myValue = value; }
}
In this instance, if I manually assign _myValue = 12, obviously the "Set" accessor for the MyValue property won't be called; I completely bypassed it! The same is true for DependencyProperties. WPF's binding system uses the DependencyProperty interfaces directly.
I have a custom Dependency Property defined like so:
public static readonly DependencyProperty MyDependencyProperty =
DependencyProperty.Register(
"MyCustomProperty", typeof(string), typeof(MyClass));
private string _myProperty;
public string MyCustomProperty
{
get { return (string)GetValue(MyDependencyProperty); }
set
{
SetValue(MyDependencyProperty, value);
}
}
Now I try set that property in XAML
<controls:TargetCatalogControl MyCustomProperty="Boo" />
But the setter in DependencyObject never gets hit! Although it does when I change the property to be a regular property and not a Dep Prop
Try this..
public string MyCustomProperty
{
get
{
return (string)GetValue(MyCustomPropertyProperty);
}
set
{
SetValue(MyCustomPropertyProperty, value);
}
}
// Using a DependencyProperty as the backing store for MyCustomProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyCustomPropertyProperty =
DependencyProperty.Register("MyCustomProperty", typeof(string), typeof(TargetCatalogControl), new UIPropertyMetadata(MyPropertyChangedHandler));
public static void MyPropertyChangedHandler(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
// Get instance of current control from sender
// and property value from e.NewValue
// Set public property on TaregtCatalogControl, e.g.
((TargetCatalogControl)sender).LabelText = e.NewValue.ToString();
}
// Example public property of control
public string LabelText
{
get { return label1.Content.ToString(); }
set { label1.Content = value; }
}
It doesn't, unless you call it manually. There's a property-changed handler you can add to the DependancyProperty constructor call to be notified of when the property changes.
Call this constructor:
http://msdn.microsoft.com/en-us/library/ms597502.aspx
With a PropertyMetadata instance created by this constructor:
http://msdn.microsoft.com/en-us/library/ms557327.aspx
EDIT: Also, you are not implementing the dependancy property correctly. Your get and set should use GetValue and SetValue respectively, and you should not have a class member to store the value. The member name of the DP should also be {PropertyName}Property, e.g. MyCustomPropertyProperty if the get/set and property name as registered is MyCustomProperty. See http://msdn.microsoft.com/en-us/library/ms753358.aspx for more information.
Hope that helps.
Maybe you are using MVVM, and overriding the DataContext of your View ?
If you do, then the event for changing MyCustomProperty will be raised on the original DataContext and not on the new ViewModel.