Reputation: 2461
Edit: Old code removed
I place it on my MainWindow.xaml
<SpinTextBlock:SpinTextBlock Text="{Binding Path=DataContext.WelcomeTitle, ElementName=Window,UpdateSourceTrigger=PropertyChanged}" Height="60" Width="40" x:Name="TextBlock"/>
And bind it to a property in MainViewModel.cs
public string WelcomeTitle
{
get
{
return _welcomeTitle;
}
set
{
if (_welcomeTitle == value)
{
return;
}
_welcomeTitle = value;
RaisePropertyChanged(WelcomeTitle);
Dispatcher.CurrentDispatcher.BeginInvoke(
new Action<String>(RaisePropertyChanged),
DispatcherPriority.DataBind, "WelcomeTitle");
}
}
Everything works fine, except that property Text in my UserControl doesn't update when the value in the ViewModel is updated. Instead the update from the ViewModel is directly placed on the TextBlock (in the UserControl) and the storyboard and all properties on my usercontrol isn't called at all.
Anyone got a solution to this?
EDIT WORKING SOLUTION
Usercontrol code-behind. Had to listen for the property change to start my storyboard and update properties.
public partial class SpinTextBlock : INotifyPropertyChanged
{
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(SpinTextBlock), new FrameworkPropertyMetadata(
string.Empty,
new PropertyChangedCallback(OnTextPropertyChanged)));
private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
SpinTextBlock obj = d as SpinTextBlock;
obj.OnTextChanged(e.NewValue as string);
}
private void OnTextChanged(string newValue)
{
UpdateTextBlocks(newValue);
}
public static readonly DependencyProperty TextOldProperty =
DependencyProperty.Register("TextOld", typeof(string), typeof(SpinTextBlock), new PropertyMetadata(default(string)));
public string Text
{
get
{
return (string)GetValue(TextProperty);
}
set
{
SetValue(TextProperty, value);
}
}
private string TextOld
{
get
{
return (string)GetValue(TextOldProperty);
}
set
{
SetValue(TextOldProperty, value);
}
}
public bool AddZeroBeforeTextIfSingleValue { get; set; }
public SpinTextBlock()
{
InitializeComponent();
AddZeroBeforeTextIfSingleValue = true;
TextBlockOld.Visibility = Visibility.Collapsed;
}
void UpdateTextBlocks(string newValue)
{
if (AddZeroBeforeTextIfSingleValue)
{
AddZeroToValue(ref newValue);
}
TextOld = TextBlockMain.Text;
StartAnimation();
}
void StartAnimation()
{
TextBlockOld.Visibility = Visibility.Visible;
Storyboard sb = this.Resources["StoryboardChangeTexts"] as Storyboard;
sb.Begin();
}
void AddZeroToValue(ref string value)
{
if (value != null && value.Length == 1)
{
value = "0" + value;
}
}
public event PropertyChangedEventHandler PropertyChanged;
UserControl xaml
<UserControl x:Class="Y.Infrastructure.SpinTextBlock.SpinTextBlock"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="userControl"
mc:Ignorable="d"
FontSize="36"
Foreground="Black"
d:DesignHeight="60" d:DesignWidth="40">
<UserControl.Resources>
<Storyboard x:Key="StoryboardChangeTexts">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="TextBlockOld">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="TextBlockMain">
<EasingDoubleKeyFrame KeyTime="0" Value="-35"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="TextBlockOld">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="35"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="Black">
<TextBlock HorizontalAlignment="Center" x:FieldModifier="private" Foreground="White" FontSize="36" Text="{Binding Text, ElementName=userControl}" x:Name="TextBlockMain" FontWeight="Bold" FontFamily="Segoe UI Semibold">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock HorizontalAlignment="Center" x:FieldModifier="private" Foreground="White" FontSize="36" Text="{Binding TextOld, ElementName=userControl}" x:Name="TextBlockOld" FontWeight="Bold" FontFamily="Segoe UI Semibold">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
</Grid>
Upvotes: 3
Views: 1582
Reputation: 35554
The call UpdateTextBlocks(value)
in the setter of your property Text
will not be called, cause the runtime will call SetValue(TextProperty, value);
directly.
Upvotes: 2