【问题标题】:XAML Data Binding: Unexpected results when setting class property from within DispatcherTimer's tick eventXAML 数据绑定:从 DispatcherTimer 的滴答事件中设置类属性时出现意外结果
【发布时间】:2015-11-04 05:18:22
【问题描述】:

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

背景:如果代码放置 (A) ,MainPage.xaml 上的绑定元素不会从 DataContext (ClockDispatcher.cs) 接收数据所需位置在类中执行。

MainPage.xaml 上的绑定元素在代码放置 (B) 时从 DataContext (ClockDispatcher.cs) 接收数据仅测试常规绑定 在类中执行。

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

问题:我的逻辑中是否存在错误,会阻止设置类属性的能力,并将结果传递给关联的绑定元素?请注意,类属性分配发生在 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; }
    }
}

【问题讨论】:

    标签: c# xaml binding


    【解决方案1】:

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

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

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

    修复 公共类时钟: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));
            }
    
        }
    

    【讨论】:

    • 非常感谢您提供的代码示例。结合您的示例和@kirotab 的输入,我能够继续前进。
    【解决方案2】:

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

    INotifyPropertyChanged Interface MSDN 这个例子在Win Forms 项目中给出,但本质上它与WPF 相同。

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

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

    【讨论】:

    • 非常感谢您的回复。它帮助我找到了解决问题的正确方向。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多