Notify if xaml calls SetValue() of a Dependency Property - wpf

I want to draw lines in UserControls that are in a ListBox. The number of lines is a Dependency Property and is set via Xaml Style. If the property has changed, I want to draw the lines. But Setters aren't called, if property is changed by xaml. Xaml calls SetValue() itself. But I need to know, when this property is changed to call my function for drawing the lines. If I call this function in the constructor, the property isn't bound yet. Can anyone help me please.

You can add PropertyChanged callback to your DependencyProperty declaration like
public static readonly DependencyProperty LineCountProperty = DependencyProperty.Register(
"LineCount",
typeof(int),
typeof(Window),
new FrameworkPropertyMetadata(
0,
new PropertyChangedCallback(OnLineCountChanged)
)
);
private static void OnLineCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//Here you call you function on `d` by typecasting it into your class
}

Related

Why does PropertyChangedCallback method not execute from Dependency Property OverrideMetadata?

I have a class called CustomGrid which derives from the Grid class. I am attempting to run a method when there are changes made to the grid's parent window's title by using OverrideMetadata on the Window class's TitleProperty. My approach to this problem, however, does not seem to work despite having another PropertyChangedCallback method I implemented, that works, using the same approach (OverrideMetadata) for the grid's MarginProperty:
public class CustomGrid : Grid
{
static CustomGrid()
{
Type ownerType = typeof(CustomGrid);
MarginProperty.OverrideMetadata(ownerType, new FrameworkPropertyMetadata(new PropertyChangedCallback(OnMarginPropertyChanged)));
Window.TitleProperty.OverrideMetadata(ownerType, new FrameworkPropertyMetadata(new PropertyChangedCallback(OnTitlePropertyChanged)));
}
private static void OnMarginPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// This executes when the grid's margin changes.
}
private static void OnTitlePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// This does not execute when the parent window's title changes.
}
}
Why does the OnTitlePropertyChanged method not execute when the grid's parent window's title is changed? Thanks.
The callback method is not called because you did not set the Window.Title property on a CustomGrid instance.
The expression
Window.TitleProperty.OverrideMetadata(
typeof(CustomGrid),
new FrameworkPropertyMetadata(OnTitlePropertyChanged));
registers the OnTitlePropertyChanged callback for the type CustomGrid. This means the callback is called whenever the dependency property is set on instances of CustomGrid, but only on those instances, not any objects like e.g. the MainWindow.

wpf properties not set after initializecomponent

I have a problem concerning properties that are set in xaml.
I've made a user control with a dependency property 'MidiChanel'.
I set the value of this property to 10 in xaml.
In the constructor of the user control, I need this value to add it to a dictionary and to pass the value to a child class of my user control.
The problem is, that in the constructor, even after calling initializecomponents, the property stil has its default value, and not the value, set in xaml.
In fact, it does't gets set at all.
If I change the 'MidiChanel' proprty to a normal property, the value gets set, but it's not initializecomponents of the userControl that sets the value, but initializecomponents of the main window.
Call stack = Main.InitializeComponents, Constructor of userControl (values are not yet available), Setter of 'MidiChanel' gets set. (by who?, call stack says Main.InitializeComponents).
I'm a winforms developer and find all this pretty strange.
After Main.InitializeComponents, I could loop over all userControls in the main page, and do everything here, but that seems a strange thing to do.
Any suggestions here?
you can set a callback method that will be raised when your dependenyProperty changed
public int SomeProp
{
get { return (int)GetValue(SomePropProperty); }
set { SetValue(SomePropProperty, value); }
}
// Using a DependencyProperty as the backing store for SomeProp. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SomePropProperty =
DependencyProperty.Register("SomeProp", typeof(int), typeof(yourOwnerclass), new PropertyMetadata(new PropertyChangedCallback(OnSomePropertyChnaged)));
public static void OnSomePropertyChnaged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as yourOwnerclass).SomeFunction();
}

Binding public property in UserControl to property on parent does not work [duplicate]

I have a WPF UserControl project named FormattedTextBox that contains a TextBox and a WPF window project in the same solution.
My user control has two dependency properties registered like this:
public static readonly DependencyProperty NumberProperty =
DependencyProperty.Register("Number",
typeof(double),
typeof(FormattedTextBox),
new FrameworkPropertyMetadata());
public static readonly DependencyProperty NumberFormatStringProperty =
DependencyProperty.Register("NumberFormatString",
typeof(string),
typeof(FormattedTextBox),
new FrameworkPropertyMetadata());
I make an instance of my usercontrol in the main window. The main window inplements INotifyPropertyChanged and has a property named MyNumber. In the XAML of the main window I try to bind to MyNumber like this:
Number="{Binding Path=MyNumber,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
The binding doesn't work - I never get into the get or set on the Number property in the user control. Can anybody help?
When a dependency property is set in XAML (or by binding or animation etc.), WPF directly accesses the underlying DependencyObject and DependencyProperty without calling the CLR wrapper. See XAML Loading and Dependency Properties,
Implications for Custom Dependency Properties.
In order to get notified about changes of the Number property, you have to register a PropertyChangedCallback:
public static readonly DependencyProperty NumberProperty =
DependencyProperty.Register("Number",
typeof(double),
typeof(FormattedTextBox),
new FrameworkPropertyMetadata(NumberPropertyChanged));
private static void NumberPropertyChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var textBox = obj as FormattedTextBox;
...
}

Binding doesn't get updated

I have class deriving from TextBox to which I attach a dependency property of type point called position and in its set section I set the Canvas.Top and Canvas.Left property. Just to clarify, whenever the source property changes it calls the set section of the property correct? Because when my source updates the canvastop and canvasleft properties of the textbox don't get updated.
Any help would be appreciated.
public static readonly DependencyProperty PositionProperty = DependencyProperty.Register("Position", typeof(Point), typeof(TextBox), new FrameworkPropertyMetadata(new Point(0, 0)));
public Point Position
{
get { return (Point)GetValue(PositionProperty); }
set
{
SetValue(PositionProperty, value);
Canvas.SetLeft(this, value.X - this.Width / 2);
Canvas.SetTop(this, value.Y - this.FontSize);
}
}
this.TextBoxShape.SetBinding(TextBoxShape.PositionProperty, CreateConnectorBinding(this));
Where CreateConnectorBinding returns the mid point of an ellipse based on it Canvas.Top and Canvas.Left properties. But when the Ellipse's Canvas.Top and Canvas. Left properties get updated the position of the textbox is still not updated.
Just to clarify, whenever the source property changes it calls the set section of the property correct?
No. This only happens when you call the property from code. The binding system bypasses the setter entirely.
If you need to do this, the proper way is to use Property Changed Callbacks registered in the DP's Metadata.
When the PositionProperty value changes via the binding, it does not use the setter. You need to add a PropertyChangeCallback to the FrameworkPropertyMetadata on your DependencyProperty registration:
public static readonly DependencyProperty PositionProperty =
DependencyProperty.Register("Position", typeof(Point), typeof(TextBox),
new FrameworkPropertyMetadata(new Point(0, 0), PositionChanged));
private static void PositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
YourControl control = (YourControl)d;
Canvas.SetLeft(d, d.Position.X - d.Width / 2);
Canvas.SetTop(d, d.Position.Y - d.FontSize);
}

wpf how to tell when databinding has finished?

I've got a custom control which has a DependencyProperty MyAnimal - I'm binding an Animal Property on my ViewModel to the MyAnimal DependencyProperty.
I've stuck a TextBox on the Control so I can trigger an Event - whenever I trigger the event the MyAnimal property has been set - however if I put a break point on the Setter of the MyAnimal property it never gets fired!
I guess I'm missing something fundamental about WPF Dependency Properties/Binding?!
And so my question is, if I can't use the Setter how can I find out when its been set? If I put if I put a break point after InitializeComponent() its null and I had a look to see if theres an Event a can hook up to - DatabindingFinished or similar? but can't see what it would be ...
Can anyone assist please?
Thanks,
Andy
public partial class ControlStrip
{
public ControlStrip()
{
InitializeComponent();
}
public Animal MyAnimal
{
get
{
return (Animal)GetValue(MyAnimalProperty);
}
set
{
SetValue(MyAnimalProperty, value);
}
}
public static readonly DependencyProperty MyAnimalProperty =
DependencyProperty.RegisterAttached("MyAnimal", typeof (Animal), typeof (ControlStrip));
private void TextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
var myAnimal = MyAnimal;
MessageBox.Show(myAnimal.Name);
}
}
The setter methods are never called by the runtime. They go directly to the DependencyProperty. You will need to add an additional argument to your call to RegisterAttached(). There you can add a PropertyChangedCallback.
Here is some sample code:
public static readonly DependencyProperty MyAnimalProperty =
DependencyProperty.RegisterAttached("MyAnimal", typeof (Animal), typeof (ControlStrip), new PropertyMetadata(AnimalChanged));
private static void AnimalChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
// Do work here
}
The setter is only there for your use - you actually can leave the property off entirely, since DataBinding uses the actual DependencyProperty itself, not the CLR property.
If you need to see when the property changes, you will need to specify PropertyMetadata on your dependency property, and provide a PropertyChangedCallback.
For details, I recommend reading Dependency Property Metadata.

Resources