Solved. Clemens was partially right - nothing was wrong with my code, property did get notified with changes. My problems were elsewhere - with a variable that didn't get value before property changed, and default value of dependency property. I sorted out those things now, and It works as expected.
Here is my full code, might get useful to someone, at least I find It so:
It's a custom Border, which can be used for a sliding animation of left Margin. Meaning you can use this Border to slide some menues to View from left side to desired right location, just add controls inside It and you're ready to go. Code can be used for other controls too (Panel etc.), but I used Border since I can round corners or do other nice UI presentations with it easily.
Logic behind is that If you set MoveTo property, Border will slide to desired left Margin location. If you don't, then Border will slide to center of screen - meaning you can use this Border for sliding menues into Views that are centered or left aligned in yout MainWindow. That was actually whole point of creating It - because you cannot use dynamic values in animation To or From, since these are freezables. So I had to create this custom control, because I couldn't do an animation to screen center (width needs to be calculated first). Anyway, here It is:
public class Border_slide : Border
{
public Border_slide()
{
Loaded += Border_slide_Loaded;
}
private void Border_slide_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
StartX = Margin.Left;
}
private double StartX
{
get { return _startX; }
set { _startX = value; }
}
private double _startX;
public static DependencyProperty MoveToProperty =
DependencyProperty.Register("MoveTo", typeof(double), typeof(Border_slide), new PropertyMetadata(default(double)));
public double MoveTo
{
get { return (double)GetValue(MoveToProperty); }
set { SetValue(MoveToProperty, value); }
}
public bool ShowSlide
{
get { return (bool)GetValue(ShowSlideProperty); }
set { SetValue(ShowSlideProperty, value); }
}
public static readonly DependencyProperty ShowSlideProperty =
DependencyProperty.Register("ShowSlide", typeof(bool), typeof(Border_slide), new FrameworkPropertyMetadata(true,
new PropertyChangedCallback(ShowSlideChanged)));
private static void ShowSlideChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var brd = d as Border_slide;
if (((bool)e.NewValue) == true)
{
ThicknessAnimation back_to_start_X_location = new ThicknessAnimation
{
BeginTime = TimeSpan.FromSeconds(0),
Duration = TimeSpan.FromSeconds(1),
From = new Thickness(brd.Margin.Left, 0, 0, 0),
To = new Thickness(brd.StartX, 0, 0, 0)
};
brd.BeginAnimation(Border.MarginProperty, back_to_start_X_location);
}
else
{
if (brd.MoveTo == default(double))
{
var X_center = Application.Current.MainWindow.ActualWidth / 2 - brd.Width / 2;
ThicknessAnimation to_center_X_location = new ThicknessAnimation
{
BeginTime = TimeSpan.FromSeconds(0),
Duration = TimeSpan.FromSeconds(1),
From = new Thickness(brd.ZacetniX, 0, 0, 0),
To = new Thickness(X_center, 0, 0, 0)
};
brd.BeginAnimation(Border.MarginProperty, to_center_X_location);
}
else
{
ThicknessAnimation to_desired_X_location = new ThicknessAnimation
{
BeginTime = TimeSpan.FromSeconds(0),
Duration = TimeSpan.FromSeconds(1),
From = new Thickness(brd.StartX, 0, 0, 0),
To = new Thickness(brd.MoveTo, 0, 0, 0)
};
brd.BeginAnimation(Border.MarginProperty, to_desired_X_location);
}
}
}
}
So, as you see - Border moves depending on what you set as start Margin.Left (that is a must) and/or MoveTo property, with binding to some bool value from ViewModel. In my case, I slide this Border when I disable all my other controls in View - so that I can make blur effect on View too. If you will use It for different things, than be careful about default value of ShowSlide property (mine is true). And surely you can re-adjust control for different things too...
E.g. usage in XAML:
<my_controls:Border_slide Margin="-500,0,0,0" MoveTo="5" ShowSlide="{Binding Enable_control}">