WPF Binding Expression and Dependency property - wpf

I am trying to bind a text box to a dependency property to change its width. The following code is not working. Any help?
public class ToolbarManager : DependencyObject
{
public static readonly DependencyProperty toolbarButtonWidth = DependencyProperty.Register("toolbarButtonWidth", typeof(Double), typeof(ToolbarManager), new FrameworkPropertyMetadata(32.0, FrameworkPropertyMetadataOptions.AffectsMeasure ));
public static readonly DependencyProperty toolbarButtonHeight = DependencyProperty.Register("toolbarButtonHeight", typeof(Double), typeof(ToolbarManager), new FrameworkPropertyMetadata(32.0, FrameworkPropertyMetadataOptions.AffectsMeasure));
public double ButtonWidth
{
get { return (double)GetValue(toolbarButtonWidth); }
set { SetValue(toolbarButtonWidth, value); }
}
public double ButtonHeight
{
get { return (double)GetValue(toolbarButtonHeight); }
set { SetValue(toolbarButtonHeight, value); }
}
public static ToolbarManager Instance { get; private set; }
static ToolbarManager()
{
Instance = new ToolbarManager();
}
}
Here is the markup code:
<TextBox Width="{Binding Source={x:Static local:ToolbarManager.Instance}, Path=ButtonWidth, Mode=OneWay}" />
The default value works, but if I modify the value in code nothing happens ?!!!

rename your dependency property should solve your problem
public class ToolbarManager : DependencyObject
{
public static readonly DependencyProperty ButtonWidthProperty =
DependencyProperty.Register("ButtonWidth", typeof(Double), typeof(ToolbarManager), new FrameworkPropertyMetadata(32.0, FrameworkPropertyMetadataOptions.AffectsMeasure ));
public static readonly DependencyProperty ButtonHeightProperty =
DependencyProperty.Register("ButtonHeight", typeof(Double), typeof(ToolbarManager), new FrameworkPropertyMetadata(32.0, FrameworkPropertyMetadataOptions.AffectsMeasure));
public double ButtonWidth
{
get { return (double)GetValue(ButtonWidthProperty); }
set { SetValue(ButtonWidthProperty, value); }
}
public double ButtonHeight
{
get { return (double)GetValue(ButtonHeightProperty); }
set { SetValue(ButtonHeightProperty, value); }
}
public static ToolbarManager Instance { get; private set; }
static ToolbarManager()
{
Instance = new ToolbarManager();
}
}
hope this helps

Related

WPF PropertyPath on Custom control

I have a problem, I create a control named Tile (like the Tile on Windows 10).
This tile simulate rotation 3D by using a projection class, like the projection class in Silverlight.
We have a base projection class like this :
abstract public class Projection
: FrameworkElement
{
static public readonly DependencyProperty RotationZProperty = DependencyProperty.Register(
nameof(RotationZ),
typeof(double),
typeof(Projection),
new UIPropertyMetadata(0.0, OnRotationChanged));
static public readonly DependencyProperty RotationYProperty = DependencyProperty.Register(
nameof(RotationY),
typeof(double),
typeof(Projection),
new UIPropertyMetadata(0.0, OnRotationChanged));
static public readonly DependencyProperty RotationXProperty = DependencyProperty.Register(
nameof(RotationX),
typeof(double),
typeof(Projection),
new UIPropertyMetadata(0.0, OnRotationChanged));
public double RotationZ
{
get { return this.GetValue<double>(RotationZProperty); }
set { SetValue(RotationZProperty, value); }
}
public double RotationY
{
get { return this.GetValue<double>(RotationYProperty); }
set { SetValue(RotationYProperty, value); }
}
public double RotationX
{
get { return this.GetValue<double>(RotationXProperty); }
set { SetValue(RotationXProperty, value); }
}
public FrameworkElement Child
{
get;
set;
}
static private void OnRotationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is Projection pl)
{
pl.OnRotationChanged();
}
}
private void OnRotationChanged()
{
// Some code
}}
After that, we have the PlaneProjectionClass :
[ContentProperty("Child")]
sealed public class PlaneProjection
: Projection
{
}
The Tile class use a dependency property of type Projection :
public class Tile
{
static public readonly DependencyProperty PlaneProjectionProperty = DependencyProperty.Register(
nameof(Projection),
typeof(Projection),
typeof(Tile),
new UIPropertyMetadata());
public Projection Projection
{
get { return (Projection)GetValue(PlaneProjectionProperty); }
private set { SetValue(PlaneProjectionProperty, value); }
}
override public void OnApplyTemplate()
{
Projection = GetTemplateChild("PART_Projection") as Projection;
}
}
So for the XAML, we have this in ControlTemplate :
<controls:PlaneProjection x:Name="PART_PlaneProjection">
<Border>
<Grid>
<!-- Some design -->
</Grid>
</Border>
</controls:PlaneProjection>
Now I would like to animate the planeprojection.
So I create the storyboard and animate the projection with rotationX :
static public void CreateAnimation(Tile tile)
{
Storyboard.SetTarget(anim, tile);
Storyboard.SetTargetProperty(doubleAnim, new PropertyPath("(Tile.Projection).(PlaneProjection.RotationX"));
}
But at debug, I have this error : Cannot resolve all references of the property on the path of the property '(Tile.Projection).(PlaneProjection.RotationX)
I don't understand the mistake :( Any ideas on using PropertyPath on custom control ?
The Projection property in class Tile does not follow the naming conventions for dependency properties.
It should e.g. look like this:
public static readonly DependencyProperty PlaneProjectionProperty =
DependencyProperty.Register(nameof(PlaneProjection), typeof(Projection), typeof(Tile));
public Projection PlaneProjection
{
get { return (Projection)GetValue(PlaneProjectionProperty); }
private set { SetValue(PlaneProjectionProperty, value); }
}
The property path would simply be this:
Storyboard.SetTargetProperty(anim, new PropertyPath("PlaneProjection.RotationX"));
You wouldn't even need a Storyboard. Just call
tile.PlaneProjection.BeginAnimation(Projection.RotationXProperty, anim);
As a note, a private setter does not make the dependency property read-only. See Read-Only Dependency Properties for details.

doing some mathematical calculation on custom dependency property values

I have three dependency property. TestControlHeight, HalfValue1 and HalfValue2. Now, depending on these three value I have to calculate
a third value which will be assigned as the height of the inner control which will also be a dependency property.
height of inner control = TestControlHeight/ (HalfValue1 - HalfValue2);
Where can I write this code to calculate the height of the inner control (which si also a dependency property)
public static readonly DependencyProperty TestControlHeightProperty =
DependencyProperty.Register("TestControlHeight", typeof (double),
typeof (TestControl), new PropertyMetadata(default(double)));
public double TestControlHeight
{
get { return (double) GetValue(TestControlHeightProperty); }
set { SetValue(TestControlHeightProperty, value); }
}
public static readonly DependencyProperty HalfValue1Property =
DependencyProperty.Register("HalfValue1", typeof (double), typeof
(TestControl), new PropertyMetadata(default(double)));
public double HalfValue1
{
get { return (double) GetValue(HalfValue1Property); }
set { SetValue(HalfValue1Property, value); }
}
public static readonly DependencyProperty HalfValue2Property =
DependencyProperty.Register("HalfValue2", typeof (double), typeof
(TestControl), new PropertyMetadata(default(double)));
public double HalfValue2
{
get { return (double) GetValue(HalfValue2Property); }
set { SetValue(HalfValue2Property, value); }
}
Thanks & Regards,
From the WPF Unleashed book:
.NET property wrappers are bypassed at runtime when setting dependency properties
in XAML!
Although the XAML compiler depends on the property wrapper at compile time, WPF calls the underlying GetValue and SetValue methods directly at runtime! Therefore, to maintain parity between setting a property in XAML and procedural code, it’s crucial that property wrappers not contain any logic in addition to the GetValue/SetValue calls.
If you want to add custom logic, that’s what the registered callbacks are for. All of WPF’s built-in property wrappers abide by this rule, so this warning is for anyone writing a custom class with its own dependency properties.
So, your code could look like this (not tested):
public static readonly DependencyProperty TestControlHeightProperty =
DependencyProperty.Register("TestControlHeight", typeof(double), typeof(TestControl),
new PropertyMetadata(false, new PropertyChangedCallback(OnHeightChanged)));
public double TestControlHeight
{
get { return (double)GetValue(TestControlHeightProperty); }
set { SetValue(TestControlHeightProperty, value); }
}
public static readonly DependencyProperty HalfValue1Property =
DependencyProperty.Register("HalfValue1", typeof(double), typeof(TestControl),
new PropertyMetadata(false, new PropertyChangedCallback(OnHeightChanged)));
public double HalfValue1
{
get { return (double)GetValue(HalfValue1Property); }
set { SetValue(HalfValue1Property, value); }
}
public static readonly DependencyProperty HalfValue2Property =
DependencyProperty.Register("HalfValue2", typeof(double), typeof(TestControl),
new PropertyMetadata(false, new PropertyChangedCallback(OnHeightChanged)));
public double HalfValue2
{
get { return (double)GetValue(HalfValue2Property); }
set { SetValue(HalfValue2Property, value); }
}
public double MyInnerControlHeight
{
get { return (double)GetValue(MyInnerControlHeightPropertyProperty); }
set { SetValue(MyInnerControlHeightPropertyProperty, value); }
}
public static readonly DependencyProperty MyInnerControlHeightPropertyProperty =
DependencyProperty.Register("MyInnerControlHeightProperty", typeof(double), typeof(TestControl),
new PropertyMetadata(0));
private static void OnHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var testControl = d as TestControl;
if (testControl != null)
{
testControl.MyInnerControlHeight = testControl.TestControlHeight / (testControl.HalfValue1 - testControl.HalfValue2);
}
}

Dependent DependencyProperty

I want to make a dependency property whose value depend on other dependency property but still settable/writable. For example, ‘DateOfBirth’ is an independent DependencyProperty. Now I want to make another DependencyProperty with name YearOfBirth. When DateOfBirth with Change it will Coerce the value of YearOfBirth property. i.e. d.CoerceValue(YearOfBirthProperty).
But How can I make dependent dependency property (e.g. YearOfBirth) writeable/settable?
If I code using CLR Properties, it works fine but how can do by using Dependency Properties!
What about this:
public partial class MainWindow : Window
{
public static DependencyProperty DateofBirthProperty = DependencyProperty.Register("DateofBirth", typeof(DateTime), typeof(MainWindow), new FrameworkPropertyMetadata(new PropertyChangedCallback(DateofBirth_Changed)));
public DateTime DateofBirth
{
get { return (DateTime)GetValue(DateofBirthProperty); }
set { SetValue(DateofBirthProperty, value); }
}
private static void DateofBirth_Changed(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
MainWindow thisClass = (MainWindow)o;
thisClass.SetDateofBirth();
}
private void SetDateofBirth()
{
DOBYear = DateofBirth.Year;
}
public static DependencyProperty DOBYearProperty = DependencyProperty.Register("DOBYear", typeof(int), typeof(MainWindow), new FrameworkPropertyMetadata(new PropertyChangedCallback(DOBYear_Changed)));
public int DOBYear
{
get { return (int)GetValue(DOBYearProperty); }
set { SetValue(DOBYearProperty, value); }
}
private static void DOBYear_Changed(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
MainWindow thisClass = (MainWindow)o;
thisClass.SetDOBYear();
}
private void SetDOBYear()
{
//Put Instance DOBYear Property Changed code here
}
public MainWindow()
{
InitializeComponent();
}
}

WPF Custom Button Control Command Not Firing

I created an override of a button:
public class LauncherButton : Button
{
public ImageSource ImageSource
{
get { return (ImageSource)GetValue(ImageSourceProperty); }
set { SetValue(ImageSourceProperty, value); }
}
public static readonly DependencyProperty ImageSourceProperty =
DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(LauncherButton), new UIPropertyMetadata(null));
public string Caption
{
get { return (string)GetValue(CaptionProperty); }
set { SetValue(CaptionProperty, value); }
}
public static readonly DependencyProperty CaptionProperty =
DependencyProperty.Register("Caption", typeof(string), typeof(LauncherButton), new UIPropertyMetadata(null));
public ICommand ExecuteCommand
{
get { return (ICommand)GetValue(ExecuteCommandProperty); }
set { SetValue(ExecuteCommandProperty, value); }
}
public static readonly DependencyProperty ExecuteCommandProperty
= DependencyProperty.Register("ExecuteCommand", typeof(ICommand), typeof(LauncherButton));
}
I use it here:
<controls:LauncherButton Caption="Job Phases"
ImageSource="/FMG.UI.WPF.Shared;component/Media/Images/jobphase_128.png"
Margin="10"
Style="{StaticResource TabletLauncherButtonStyle}"
ExecuteCommand="{Binding ItemSelectedCommand}"
CommandParameter="{x:Static enums:View.JobPhases}"/>
and the view's VM:
public class TabletHomeViewModel : _HomeViewBase
{
private ICommand _ItemSelectedCommand;
public ICommand ItemSelectedCommand
{
get
{
if (_ItemSelectedCommand == null)
_ItemSelectedCommand = new RelayCommand(p => itemSelecteExecuted((View)p), p => itemSelecteCanExecute((View)p));
return _ItemSelectedCommand;
}
}
private bool itemSelecteCanExecute(View view)
{
return true;
}
private void itemSelecteExecuted(View view)
{
}
}
The ItemSelectedCommand's Getter fires on startup, but when I click on the button, the command doesn't fire. The Output Window doesn't show any binding problems.
If I wire up a click event for it, that does fire.
Anyone see what's wrong?
Thanks

DependencyProperty and WPF Designer

class MyLine : Shape {
public static readonly DependencyProperty X11Property;
public static readonly DependencyProperty X22Property;
public static readonly DependencyProperty Y11Property;
public static readonly DependencyProperty Y22Property;
static MyLine() {
X11Property = DependencyProperty.Register("X11", typeof(double), typeof(MyLine), new UIPropertyMetadata(double.NaN));
X22Property = DependencyProperty.Register("X22", typeof(double), typeof(MyLine), new UIPropertyMetadata(double.NaN));
Y11Property = DependencyProperty.Register("Y11", typeof(double), typeof(MyLine), new UIPropertyMetadata(double.NaN));
Y22Property = DependencyProperty.Register("Y22", typeof(double), typeof(MyLine), new UIPropertyMetadata(double.NaN));
}
[TypeConverter(typeof(LengthConverter))]
public double X11 { get { return (double)GetValue(X11Property); } set { SetValue(X11Property, value); } }
[TypeConverter(typeof(LengthConverter))]
public double X22 { get { return (double)GetValue(X22Property); } set { SetValue(X22Property, value); } }
[TypeConverter(typeof(LengthConverter))]
public double Y11 { get { return (double)GetValue(Y11Property); } set { SetValue(Y11Property, value); } }
[TypeConverter(typeof(LengthConverter))]
public double Y22 { get { return (double)GetValue(Y22Property); } set { SetValue(Y22Property, value); } }
protected override System.Windows.Media.Geometry DefiningGeometry {
get {
var geometryGroup = new GeometryGroup();
// Add line
geometryGroup.Children.Add(new LineGeometry(new Point(X11, Y11), new Point(X22, Y22)));
return geometryGroup;
}
}
}
Why when I update the "myLine" coordinates in WPF designer(VS 2010), it does not update it automatically(live)?
When using default "Line" WPF objects, they are automatically updated when the XAML code is changed(edited) in XAML/Design view.
Since these properties affect rendering, you should specify it in the metadata:
X11Property = DependencyProperty.Register("X11", typeof(double), typeof(DirectionLine), new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsRender));
I'm not sure it will be enough for the designer to take it into account, but it's worth a try...

Resources