WPF Dependency Property Error - c#

I am trying to define a dependency property like this:
public static readonly DependencyProperty DependencyPropertyName= DependencyProperty.Register("DepName", typeof(EnumName), typeof(MyWindow1), new FrameworkPropertyMetadata("FrameWorkProperty", FrameworkPropertyMetadataOptions.AffectsRender, Target));
private static void Target(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
//some logic here
}
public EnumName DepName
{
get { return (EnumName)GetValue(DependencyPropertyName); }
set { SetValue(DependencyPropertyName, value); }
}
And i get this error, and dont understand why:
{"Default value type does not match type of property 'DepName'."}

The default value type (String) of your Dependency Property does not match the Type of your property DepName (EnumName).
Change the default type in your dependency property and it should work.
public static readonly DependencyProperty DependencyPropertyName= DependencyProperty.Register(
"DepName",
typeof(EnumName),
typeof(MyWindow1),
new FrameworkPropertyMetadata(
EnumName.SomeValue, // this is the defalt value
FrameworkPropertyMetadataOptions.AffectsRender,
Target));

Related

GetValue and SetValue vs INotifyPropertyChanged.PropertyChanged when creating BindableProprties?

I usually extend controls by creating bindable properties, in this form:
public static readonly BindableProperty OnTextProperty = BindableProperty.Create(nameof(OnText),
typeof(string), typeof(TextSwitch), defaultValue: string.Empty, defaultBindingMode: BindingMode.TwoWay,
propertyChanged: HandleOnTextPropertyChanged);
private static void HandleOnTextPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
(bindable as TextSwitch)?.Rebuild();
}
public string OnText
{
get { return (string)GetValue(OnTextProperty); }
set { SetValue(OnTextProperty, value); }
}
for me, since I did some WPF, bindable properties consists of two parts: the static readonly BindableProperty field, and a corresponding property with GetValue in getter and SetValue in setter. But I stumbled over this: https://github.com/adamped/NavigationMenu/blob/master/NavigationMenu/NavigationMenu/NavigationItem.xaml.cs
which just fire the PropertyChanged event :
public static readonly BindableProperty TextProperty = BindableProperty.Create(
nameof(Text),
typeof(string),
typeof(NavigationItem),
string.Empty,
propertyChanging: (bindable, oldValue, newValue) =>
{
var ctrl = (NavigationItem)bindable;
ctrl.Text = (string)newValue;
},
defaultBindingMode: BindingMode.OneWay);
private string _text;
public string Text
{
get { return _text; }
set
{
_text = value;
OnPropertyChanged();
}
}
How can this incorporate with the bindable properties to get it working without GetValue and SetValue?, and in which cases we need to use one approach over another?
EDIT
Apparently I'm not accustomed to the notion of the self binding reusable control.. but isn't calling GetValue and SetValue essential for binding properties?
These two implementations are the same.
GetValue(BindableProperty) and SetValue are used to access the values of properties that are implemented by a BindableProperty. That is, application developers typically provide an interface for a bound property by defining public property whose get accessor casts the result of GetValue(BindableProperty) to the appropriate type and returns it, and whose set accessor uses SetValue to set the value on the correct property.
Your achievement
private static void HandleOnTextPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
(bindable as TextSwitch)?.Rebuild();
}
is same with
propertyChanging: (bindable, oldValue, newValue) =>
{
var ctrl = (NavigationItem)bindable;
ctrl.Text = (string)newValue;
}
Used
OnPropertyChanged(); in setValuemethod

How to use BindableProperty.Create in Xamarin.Forms?

In xaml in Xamarin.Forms, I have a custom control, I want to add property of type int. I think I have to use Bindable properties, so later I can bind a property from ViewModel.
I found this topic, but I'm not sure how to use it.. there is:
BindableProperty.Create(nameof(ItemsSource), typeof(IList), typeof(BindablePicker), null,
propertyChanged: OnItemsSourcePropertyChanged);
what's "BindablePicker"? Is it the view where property is declared?
Here's my try:
public int WedgeRating
{
get
{
return (int)GetValue(WedgeRatingProperty);
}
set
{
try
{
SetValue(WedgeRatingProperty, value);
}
catch (ArgumentException ex)
{
// We need to do something here to let the user know
// the value passed in failed databinding validation
}
}
}
public static readonly BindableProperty WedgeRatingProperty =
BindableProperty.Create(nameof(WedgeRating), typeof(int), typeof(GameCocosSharpView), null, propertyChanged: OnItemsSourcePropertyChanged);
private static void OnItemsSourcePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
}
I didn't even use it in xaml, and it already doesn't work. No particular exception. Only the page where the custom control is initialized doesn't loead. When I comment line I pasted here, it works.
Your code is good, just change your default value from null to 0 or default(int). You have it as null but an int property could never be null. This was the reason of the "crash".
public static readonly BindableProperty WedgeRatingProperty =
BindableProperty.Create (nameof (WedgeRating), typeof (int), typeof (GameCocosSharpView), default(int), propertyChanged: OnItemsSourcePropertyChanged);
Hope this helps!
Here is the example for Bindable Property
public class GameCocosSharpView : View
{
public int WedgeRating
{
get { return (int)GetValue(WedgeRatingProperty); }
set { SetValue(WedgeRatingProperty, value); }
}
public static void WedgeRatingChanged(BindableObject bindable, object oldValue, object newValue)
{
}
public static readonly BindableProperty WedgeRatingProperty =
BindableProperty.Create("WedgeRating", typeof(int), typeof(GameCocosSharpView), 1, BindingMode.Default, null, WedgeRatingChanged);
}

Using bindings for dependency property XAML

Apologies for yet another Dependency property question
Following these questions:
XAML Binding on Dependency Property
A 'Binding' can only be set on a DependencyProperty of a DependencyObject
and this tutorial:
http://wpftutorial.net/DependencyProperties.html
I am having a similar problem. and after trying the solutions not much has changed.
I have made a control library: WpfCustomControlLibrary1
public class CustomControl1 : Control
{
static CustomControl1()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));
}
And added a dependency property with the required callbacks:
FrameworkPropertyMetadata meta = new FrameworkPropertyMetadata(null,FrameworkPropertyMetadataOptions.Inherits, PropertyChangedCallbackMethod, OnDictionaryCoerce,false);
public static readonly DependencyProperty DictionaryProperty = DependencyProperty.Register("DictionaryProperty",typeof(Dictionary<string,int>),
typeof(CustomControl1),new FrameworkPropertyMetadata(null,FrameworkPropertyMetadataOptions.Inherits));
private Dictionary<string, int> _Dictionary;
public static void PropertyChangedCallbackMethod(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// I am not entirely sure what code should be implemented here, leaving it blank for now
}
private static Object OnDictionaryCoerce(DependencyObject sender,Object data)
{
return data;
}
private static bool OnValidate(object data)
{
return data is Dictionary<string, int>;
}
public Dictionary<string, int> Dictionary
{
get
{
return _Dictionary;
}
set
{
_Dictionary = value;
}
}
}
}
I then try to set the property to a binding in an application but am given an error saying:
How do I set my dependancy property to be a dependancy object? or is their a way to set a binding to a dependency property?
And isn't the base class of a dependency property a dependency object?
Register DP with correct name:
DependencyProperty.Register("Dictionary", ...
and then in DP wrapper property use GetValue, SetValue methods
public Dictionary<string, int> Dictionary
{
get
{
return (Dictionary<string, int>)GetValue(DictionaryProperty);
}
set
{
SetValue(DictionaryProperty, value);
}
}
private Dictionary<string, int> _Dictionary; field is not necessary

Is it wrong/bad to use INPC on a DependencyObject to support built-in conversion behavior?

We have a DependencyObject which defines a Value property as a DP. It also defines a Presets collection representing friendly names for some pre-defined values.
The way our UI should work is when we bind to the Value property, if the value matches a preset, we show the friendly name, otherwise we just show the value directly.
Using a converter is out since there's no reliable way to both pass in the Presets (which are defined per-item, they aren't shared) and also do two-way binding, so our thought is to expose a FriendlyValue property on the object and use that for binding in the UI, letting it handle the conversion internally.
Since FriendlyValue depends on the already-existing Value DependencyProperty, we figured we'd just wrap the conversion logic in CLR getters/setters, but that means when the actual Value DP changes, it needs to notify the UI that FriendlyValue has been updated too, and since FriendlyValue is a CLR property, we need to support INPC for that specific property.
My question is, is that the correct/suggested way to handle this, or should I go with a second DP, monitoring its change handlers and setting the other property accordingly, adding state variables to stop one from setting the other, which then sets the first, which then again updates the other, etc.
Here's the code for the object's properties...
public static readonly DependencyProperty PresetsProperty = DependencyProperty.Register(
"Presets",
typeof(List<Preset>),
typeof(MyObject),
new UIPropertyMetadata(null));
public List<Preset> Presets
{
get { return (List<Preset>)GetValue(PresetsProperty); }
set { SetValue(PresetsProperty, value); }
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value",
typeof(string),
typeof(MyObject),
new UIPropertyMetadata(null, (s,e) => {
var myObject = (MyObject)s;
myObject.OnPropertyChanged("FriendlyValue");
}));
public string Value
{
get { return (string)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public string FriendlyValue
{
get
{
var foundPreset = Presets.FirstOrDefault(preset => preset.Value == this.Value);
return (foundPreset != null)
? foundPreset.FriendlyName
: this.Value;
}
set
{
var foundPreset = Presets.FirstOrDefault(preset => preset.FriendlyName == value);
this.Value = (foundPreset != null)
? foundPreset.Value
: value;
// Note: We don't raise INPC notification here. It's raised in the Value's change handler
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
So is this considered good practice for built-in converter behavior?
Why not make both Value and FriendlyValue dependency properties? I see no reasons to use two techniques at the same time.
Consider:
using Preset = Tuple<string, string>;
public class MyObject : DependencyObject
{
private readonly IList<Tuple<string, string>> _presets = new List<Preset> {
new Preset("1", "good"),
new Preset("2", "bad"),
};
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value", typeof(string), typeof(MyObject),
new PropertyMetadata(null,
(o, e) => ((MyObject)o).ValuePropertyChanged((string)e.NewValue)));
private static readonly DependencyProperty FriendlyValueProperty = DependencyProperty.Register(
"FriendlyValue", typeof(string), typeof(MyObject),
new PropertyMetadata(null,
(o, e) => ((MyObject)o).FriendlyValuePropertyChanged((string)e.NewValue)));
public string Value
{
get { return (string)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public string FriendlyValue
{
get { return (string)GetValue(FriendlyValueProperty); }
set { SetValue(FriendlyValueProperty, value); }
}
private void ValuePropertyChanged (string newValue)
{
var preset = _presets.FirstOrDefault(p => p.Item1 == newValue);
FriendlyValue = preset != null ? preset.Item2 : newValue;
}
private void FriendlyValuePropertyChanged (string newValue)
{
var preset = _presets.FirstOrDefault(p => p.Item2 == newValue);
Value = preset != null ? preset.Item1 : newValue;
}
}
Notes:
Code for presets simplified for brevity.
This will not cause stack overflow, because change callback are not called if value is not changed.
I hope I understood your logic correctly. There's one issue: if you change FriendlyValue to one of the friendly values from the presets, this will change Value to the value from the found preset and in turn change FriendlyValue to the name of the preset. I don't know if that behavior is expected.

PropertyMetadata to register a DependencyProperty of Type "System.Windows.Point"?

Here is my code :
public class ExoticPoint : DependencyObject
{
public Point PointValue
{
get { return (Point)GetValue(PointValueProperty); }
set { SetValue(PointValueProperty, value); }
}
public static readonly DependencyProperty PointValueProperty =
DependencyProperty.Register("PointValue", typeof(Point), typeof(ExoticPoint), new PropertyMetadata(0));
public string Description
{
get { return (string)GetValue(DescriptionProperty); }
set { SetValue(DescriptionProperty, value); }
}
public static readonly DependencyProperty DescriptionProperty =
DependencyProperty.Register("Description", typeof(string), typeof(ExoticPoint), new UIPropertyMetadata(0));
public ExoticPoint()
{
}
public ExoticPoint (string objectName)
: base(objectName)
{
}
}
It compiles but when I want to CreateInstance of my type it crashes with the following error :
{"Default value type does not match type of property 'PointValue'."}
So Im kinda sure the problem is :
new PropertyMetadata(0)
but as far as I understand PropertyMetadata it should work as there is a Point constructor that takes an int as parameter : http://msdn.microsoft.com/en-us/library/bf1b4f2b.aspx
So... what is wrong ?
Yes you are right the problem is with the object passed into PropertyMetada.The parameter will be the default value for your property so it has to match with the type of your dependency property.
In your case PointValue type is Point so you should write new PropertyMetadata(new Point(0)).
Also your Description property which is string: new UIPropertyMetadata("0") or new UIPropertyMetadata("") depending on your needs.

Categories

Resources