Binding does not update usercontrol property correctly MVVM

与世无争的帅哥 提交于 2019-12-23 19:41:16

问题


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>


回答1:


The call UpdateTextBlocks(value) in the setter of your property Text will not be called, cause the runtime will call SetValue(TextProperty, value); directly.



来源:https://stackoverflow.com/questions/14497344/binding-does-not-update-usercontrol-property-correctly-mvvm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!