cannot convert from method group to object porting WFP => UWP - c#

For a project i've been working on i'm porting some custom controls from the WPF platform to UWP.
on the WPF side it is implemented as such:
public static readonly DependencyProperty MaxLengthProperty = DependencyProperty.Register("MaxLength", typeof(int), typeof(HexBox), new PropertyMetadata(MaxLength_PropertyChanged));
public int MaxLength
{
get { return (int)GetValue(MaxLengthProperty); }
set { SetValue(MaxLengthProperty, value); }
}
private static void MaxLength_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
HexBox hexControl = (HexBox)d;
hexControl.txtValue.MaxLength = (int)e.NewValue;
}
with the MaxLength_PropertyChanged being used without arguments.
When i try to do the same in UWP i get greeted by the following message:
Argument 1: cannot convert from 'method group' to 'object'
I know this has to do with not passing the arguments, or calling them as a method with (). but in WPF this behavior was implicit.
anyone have an idea?

Try this:
public static readonly DependencyProperty MaxLengthProperty = DependencyProperty.Register(
"MaxLength",
typeof(int),
typeof(HexBox),
new PropertyMetadata(0, new PropertyChangedCallback(MaxLength_PropertyChanged))
);
private static void MaxLength_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
HexBox hexControl = d as HexBox;
hexControl.txtValue.MaxLength = (int)e.NewValue;
}

Related

new PropertyMetadata(0.0,OnAngleChanged) vs new PropertyMetadata(0,OnAngleChanged)

Follow is CSharp code, and I want to use the attached property Angle to change the rectangles' angle in my XAML. The problem is when I change the new PropertyMetadata(0.0,OnAngleChanged) tonew PropertyMetadata(0,OnAngleChanged) then it doesn't work and throw XamlParseException and says that the type initializer for XXX.RotationManager threw an exception. I wonder why new PropertyMetadata(0,OnAngleChanged) does't work.
class RotationManager
{
public static double GetAngle(DependencyObject obj)
{
return (double)obj.GetValue(AngleProperty);
}
public static void SetAngle(DependencyObject obj, double value)
{
obj.SetValue(AngleProperty, value);
}
// Using a DependencyProperty as the backing store for Angle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AngleProperty =
DependencyProperty.RegisterAttached("Angle", typeof(double), typeof(RotationManager), new PropertyMetadata(0.0,OnAngleChanged));
private static void OnAngleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var element = d as UIElement;
if (element!=null)
{
element.RenderTransformOrigin = new Point(.5, .5);
element.RenderTransform = new System.Windows.Media.RotateTransform((double)e.NewValue);
}
}
}
because the first parameter of PropertyMetaData() is the same type as GetAngle and SetAngle, when you change the type of GetAngle and SetAngle to int, and the new PropertyMetadata(0,OnAngleChanged) can work.
However, changing the property type to int isn't feasible. It should have the same type as the property that it is assigned to later, i.e. RotateTransform.Angle, which is double.
The best solution would be to not specify a default value at all, and thus implicitly get 0.0 or default(double) as default value:
public static readonly DependencyProperty AngleProperty =
DependencyProperty.RegisterAttached(
"Angle", typeof(double), typeof(RotationManager),
new PropertyMetadata(new PropertyChangedCallback(OnAngleChanged)));

Dependencey Property with New Object in designer

I am struggling to find information about how to add some extra functionality in Visual Studio for dependency properties.
Basically, I want to create a similar function as the Effect property on most controls. If I press the Effects' new button, a list of possible effect objects are shown.
This is what I am used to for DP
public MyClass MyClass
{
get { return (MyClass)GetValue(MyClassProperty); }
set { SetValue(MyClassProperty, value); }
}
public static readonly DependencyProperty MyClassProperty =
DependencyProperty.Register("MyClass", typeof(MyClass),
typeof(MyView),
new FrameworkPropertyMetadata(new MyClass(), FrameworkPropertyMetadataOptions.AffectsRender, MyClassPropertyChangedCallback));
private static void MyClassPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = d as MyView;
control.MyClass = (MyClass)e.NewValue;
}

Attached Property + Style -> ArgumentNullException

I have created a very Simple attached Property:
public static class ToolBarEx
{
public static readonly DependencyProperty FocusedExProperty =
DependencyProperty.RegisterAttached(
"FocusedEx", typeof(bool?), typeof(FrameworkElement),
new FrameworkPropertyMetadata(false, FocusedExChanged));
private static void FocusedExChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is ToolBar)
{
if (e.NewValue is bool)
{
if ((bool)e.NewValue)
{
(d as ToolBar).Focus();
}
}
}
}
public static bool? GetFocusedEx(DependencyObject obj)
{
return (bool)obj.GetValue(FocusedExProperty);
}
public static void SetFocusedEx(DependencyObject obj, bool? value)
{
obj.SetValue(FocusedExProperty, value);
}
}
Setting this in Xaml works perfectly fine, but if I try setting it within a Style:
I receive an ArguemntNullException during the Runtime (saying: "Value cannot be null.
Parameter name: property").
I cannot figure what is wrong here. Any hint is appriciated!
A common mistake made when registering attached dependency properties is to incorrectly specify the ownerType argument. This must always be the registering class, ToolBarEx here:
public static readonly DependencyProperty FocusedExProperty =
DependencyProperty.RegisterAttached(
"FocusedEx", typeof(bool?), typeof(ToolBarEx),
new FrameworkPropertyMetadata(false, FocusedExChanged));
And just for avoiding unnecessary code in the property changed handler you could safely cast NewValue to bool:
private static void FocusedExChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var toolBar = d as ToolBar;
if (toolBar != null && (bool)e.NewValue)
{
toolBar.Focus();
}
}

Private WPF dependency property

In my WPF project I need to animate several properties with the same value. So my idea was to create a custom, private dependency property to which the animation will be applied. Unfortunately this doesn't seem to work. DependencyPropertyDescriptor.FromProperty() always returns null for this property. Here is the code:
public partial class PedestrianVisual : UserControl {
private static readonly DependencyProperty CurrentInaccuracyRadiusProperty =
DependencyProperty.Register("CurrentInaccuracyRadius", typeof(double), typeof(PedestrianVisual));
private double CurrentInaccuracyRadius {
get { return (double)GetValue(CurrentInaccuracyRadiusProperty); }
set { SetValue(CurrentInaccuracyRadiusProperty, value); }
}
public PedestrianVisual() {
InitializeComponent();
// This returns "null" all the time.
DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(
CurrentInaccuracyRadiusProperty, typeof(PedestrianVisual));
dpd.AddValueChanged(this, (s, e) => {
UpdateInaccuracyCircle((double)GetValue(CurrentInaccuracyRadiusProperty));
});
}
private void UpdateInaccuracyCircle(double curRadius) {
// do something here
}
}
Is there any other way to create a private dependency property?
I don't understand why you would do it that way, i did not encounter any problems when attaching the callback in the declaration, e.g. something like this:
private static readonly DependencyProperty CurrentInaccuracyRadiusProperty =
DependencyProperty.Register
(
"CurrentInaccuracyRadius",
typeof(double),
typeof(PedestrianVisual),
new UIPropertyMetadata(0.0, (s, e) =>
{
UpdateInaccuracyCircle((PedestrianVisual)s, (double)e.NewValue);
})
);
(UpdateInaccuracyCircle method should be static in this case)
If you want to stick with the instance method:
private static readonly DependencyProperty CurrentInaccuracyRadiusProperty =
DependencyProperty.Register
(
"CurrentInaccuracyRadius",
typeof(double),
typeof(PedestrianVisual),
new UIPropertyMetadata(0.0, (s, e) =>
{
((PedestrianVisual)s).UpdateInaccuracyCircle((double)e.NewValue);
})
);
To further update H.B's answer, the standard approach is along these lines:
static readonly DependencyProperty CurrentInaccuracyRadiusProperty =
DependencyProperty.Register
(
"CurrentInaccuracyRadius",
typeof(double),
typeof(PedestrianVisual),
new UIPropertyMetadata(0.0, OnCurrentInaccuracyRadiusChanged)
);
static void OnCurrentInaccuracyRadiusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var pedVisual = d as PedestrianVisual;
if (pedVisual != null)
pedVisual.OnCurrentInaccuracyRadiusChanged((double)e.OldValue, (double)e.NewValue);
}
void OnCurrentInaccuracyRadiusChanged(double oldValue, double newValue)
{
UpdateInaccuracyCircle(newValue);
}

How can I create a read-only Boolean dependency property that returns `And` operation between two other dependency properties

How can I create a custom read-only Boolean dependency property that returns And operation between two custom Boolean dependency properties, for example (A, B),
And when A or B changes, I want the result property to trigger.
Any help to achieve that!
Part 1: dependencies.
public static readonly DependencyProperty Source1Property =
DependencyProperty.Register(
"Source1",
typeof(bool),
typeof(MyControl),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(UpdateTarget)));
public bool Source1
{
get { return (bool)GetValue(Source1Property); }
set { SetValue(Source1Property, value); }
}
void UpdateTarget(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MyControl self = (MyControl)d;
d.Target = d.Source1 && d.Source2;
}
Part 2: read-only
internal static readonly DependencyPropertyKey TargetPropertyKey =
DependencyProperty.RegisterReadOnly(
"Target",
typeof(bool),
typeof(MyControl),
new PropertyMetadata(false));
public static readonly DependencyProperty TargetProperty =
TargetPropertyKey.DependencyProperty;
public bool Target
{
get { return (bool)GetValue(TargetProperty); }
protected set { SetValue(TargetPropertyKey, value); }
}
Disclaimer: I didn't try the part 2.
Part 3:
if the source dependency properties are not defined by you, you can do the following trick:
DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(
MyControl.Source1Property,
typeof(MyControl)));
if (dpd != null)
dpd.AddValueChanged(this, UpdateTarget);
You can do this by defining your two dependency properties A and B (for the sake of the example, I guess), and define a callback to be executed whenever these changes, using PropertyMetaData in the DependencyProperty constructor. In this callback, simply perform the calculation you want and set the Result depdendency property to that value. Here is a working example:
public class Data : DependencyObject
{
public static readonly DependencyProperty AProperty = DependencyProperty.Register("A", typeof(Boolean), typeof(Data), new PropertyMetadata(false,HandleValueChanged));
public static readonly DependencyProperty BProperty = DependencyProperty.Register("B", typeof(Boolean), typeof(Data), new PropertyMetadata(false, HandleValueChanged));
public static readonly DependencyProperty ResultProperty = DependencyProperty.Register("Result",typeof (Boolean), typeof (Data));
private static void HandleValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
d.SetValue(ResultProperty, ((Data)d).Result);
Debug.WriteLine("Value change");
}
public bool Result
{
get { return A & B; }
}
public bool A
{
get { return (bool) GetValue(AProperty); }
set
{
if ( A != value )
SetValue(AProperty, value);
}
}
public bool B
{
get
{
return (bool) GetValue(BProperty);
}
set
{
if (B != value)
SetValue(BProperty, value);
}
}
}

Categories