XAML 数据绑定:从 DispatcherTimer 的滴答事件中设置 class 属性 时出现意外结果

XAML Data Binding: Unexpected results when setting class property from within DispatcherTimer's tick event

所有可能访问此主题的人,您好。我试图了解 XAML 数据绑定的基本原则。如您所见,这是一个简单的通用 Windows 程序。

背景: MainPage.xaml 上的绑定元素不会 从 DataContext (ClockDispatcher.cs) 接收数据如果代码放置 (A) desired location 在 class.

中执行

MainPage.xaml 上的绑定元素 从 DataContext (ClockDispatcher.cs) 接收数据,如果代码放置 (B) 仅测试通用绑定 在class.

中执行

调试任一代码放置选项时,本地人 windows 显示正在设置 public 属性 "MyClock.Time" IS .但是 MainPage.xaml 上的绑定元素只有在执行 CODE PLACEMENT (B) testing general binding only 时才会实现。

问题: 我的逻辑中是否存在错误,导致无法如图所示设置 class 属性 并交付该结果关联的绑定元素?请注意 class 属性 分配发生在 dispatcherTimer_Tick 方法中。

提前感谢,感谢您花时间和精力帮助我理解这个问题!

此致, DMMcCollum

MainPage.xaml

    <Page
x:Class="TestBinding.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestBinding"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:data="using:TestBinding.Models"
mc:Ignorable="d">

<Page.DataContext>
    <data:ClockDispatcher />
</Page.DataContext>

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
        <TextBlock x:Name="TimeTextBlock" Text="{Binding MyClock.Time, Mode=OneWay}" />
    </StackPanel>
</Grid>

ClockDispatcher.cs

    namespace TestBinding.Models
{
public class ClockDispatcher
    {
    //Bound to "TimeTextBlock" on MainPage.xaml
    public Models.Clock MyClock { get; private set; } = new Models.Clock();

    public ClockDispatcher() 
        {
        //CODE PLACEMENT (B)
        //If executed here - WILL set class public property and WILL BE reflected in UI (but not updated as understood) 
        //MyClock.Time = string.Format("{0}", DateTime.Now.ToString("t"));

        DispatcherTimer dispatcherTimer = new DispatcherTimer();
        dispatcherTimer.Tick += dispatcherTimer_Tick;

        dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
        dispatcherTimer.Start();
        }



    private void dispatcherTimer_Tick(object sender, object e)
        {
        //CODE PLACEMENT (A)
        //if executed here - WILL set class public property and WILL NOT BE reflected in UI (but updates property on each tick interval as understood)
        MyClock.Time = string.Format("{0}", DateTime.Now.ToString("t"));
        }
    }
}

Clock.cs

    namespace TestBinding.Models
{
public class Clock
    {
    public string Time { get; set; }
    }
}

您需要通知 View 您的 View Model 的更改,这是在 [=10= 的帮助下完成的] 接口(有很多关于如何实现它的信息)或使用一些 MVVM 框架,如:MVVM LightPrism 等。 ..

INotifyPropertyChanged Interface MSDN 该示例在 Win Forms 项目中给出,但本质上与 WPF.

相同

您可以直接将值设置到控件,但绑定不会以这种方式工作。

对于数据集合,您可以使用类似 ObservableCollection 的方式来通知视图其元素的更改,例如,您不必在添加项目时调用 Raise PropertyChanged 事件,集合会知道插入了新项目。

您应该在 class 时钟中实现 INotifyPropertyChanged,以便源或目标中的任何更改都是同步的。

为什么它在代码放置 B 中工作 - 因为 属性 值是在初始化控件之前在构造函数中设置的,因此值将始终在加载时设置。

为什么它在代码放置 A 中工作 - - 它在 window 加载后调用的不同函数中。

修复 public class 时钟:INotifyPropertyChanged { 私有字符串时间;

       public string Time 
       {

           get 
            {
               return this.time;
            }
            set
            {
               this.time = value;
               NotifyPropertyChanged("Time");
            }
         }

        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

    }