robertk
robertk

Reputation: 2461

Binding does not update usercontrol property correctly MVVM

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

Answers (1)

Jehof
Jehof

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

Related Questions