简体   繁体   中英

WPF, Property does not return value to the binding

So, I have a project with a scrolling text (marqee) that rotates over a string array. And I want it to change the string value after 20 seconds of each animation iteration.

There is a problem though, the property(ScrollingText) that uses the INotifyPropertyChanged interface to bind to a textblock(using XAML) does not return after the first iteration. Even though it refreshes normally(in the set part), it does not return on the Getter part.... except for the first set in the default ctor.

MAIN CLASS:

class GetScrollingText : CommonBase
{
    private string _scrollingtext = String.Empty;
    DoubleAnimation Animation;

    public GetScrollingText()
    {
        ScrollingText = GetScrollString();
    }

    public string ScrollingText
    {
        get
        {
            return _scrollingtext;
        }
        set
        {
            if (value != _scrollingtext)
            {
                _scrollingtext = value;
                RaisePropertyChanged("ScrollingText");
            }               
        }
    } // INJECTS the string in the animated textblock {binding}.

    public TextBlock scrollBlock { get; set; }

    string GetScrollString()
    {
        .........
        return scrolltext;
    }      

    public void LeftToRightMarqee(double from, double to)
    {
        Animation = new DoubleAnimation();
        Animation.From = from;
        Animation.To = to;
        Animation.Duration = new Duration(TimeSpan.FromSeconds(20));
        Animation.Completed += animation_Completed;
        scrollBlock.BeginAnimation(Canvas.LeftProperty, Animation);
    }

    void animation_Completed(object sender, EventArgs e)
    {
        ScrollingText = GetScrollString();           
        scrollBlock.BeginAnimation(Canvas.LeftProperty, Animation);
    }
}

For some reason the animation_Completed Event only changes the value ScrollingText, but it does not invoke the Getter part therefore there is not a return to the {binding}.

XAML:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:AnnouncingSys"
    x:Class="AnnouncingSys.MainWindow"
    x:Name="Window"
    Width="1280" Height="720" MinHeight="566" MinWidth="710">

    <Window.Resources>
        <vm:GetScrollingText x:Key="ScrollingText"/>
    </Window.Resources>
    <Canvas x:Name="MainCanvas" ClipToBounds="True" Margin="0,0,0,0" Grid.Row="5" Background="Black" Grid.ColumnSpan="5" >
        <TextBlock x:Name="ScrollBlock" TextWrapping="Wrap" VerticalAlignment="Top" Height="113" Width="5147" Canvas.Left="-1922" Text="{Binding ScrollingText, Source={StaticResource ScrollingText}}"/>
    </Canvas>
</Window>

CODE BEHIND:

public partial class MainWindow : Window
{
    GetScrollingText scrolling = new GetScrollingText();

    public MainWindow()
    {
        InitializeComponent();
        scrolling.scrollBlock = this.ScrollBlock;
        scrolling.LeftToRightMarqee(2000, -3000);
    }
}

And finally the helper class CommonBase:

public class CommonBase : INotifyPropertyChanged
{
    protected CommonBase()
    {
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string PropertyName)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;

        if (handler != null)
        {
            PropertyChangedEventArgs e = new PropertyChangedEventArgs(PropertyName);
            handler(this, e);
        }
    }
}

I have even put a breakpoint on the return block of the Getter but it only activates on the first: "ScrollingText = GetScrollString()". I mean, shouldn't it return each time the value is changed???

You are using two different instances of your GetScrollingText class, one in XAML as StaticResource, the other in code behind as the scrolling field in class MainWindow.

Instead of creating a StaticResource in XAML, you could just set the DataContext property of your MainWindow:

public partial class MainWindow : Window
{
    GetScrollingText scrolling = new GetScrollingText();

    public MainWindow()
    {
        InitializeComponent();
        scrolling.scrollBlock = this.ScrollBlock;
        scrolling.LeftToRightMarqee(2000, -3000);
        DataContext = scrolling; // here
    }
}

Now you would not explicitly set the binding's Source property, because the DataContext is used as default binding source:

<TextBlock ... Text="{Binding ScrollingText}"/>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM