Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF:未使用INotifyPropertyChanged更新UI_C#_Wpf_Xaml_Datacontext - Fatal编程技术网

C# WPF:未使用INotifyPropertyChanged更新UI

C# WPF:未使用INotifyPropertyChanged更新UI,c#,wpf,xaml,datacontext,C#,Wpf,Xaml,Datacontext,我目前正在学习WPF、数据上下文和数据绑定。我的目标是有一个任务栏任务(使用NotifyIconWpf),它有一个在后台运行的连续线程来监视网络 我已设法将UI元素(如屏幕截图所示)绑定到ProgramClock类,但它不会在ProgramClock更改时更新,很可能是因为INotifyPropertyChanged参数中的某些内容出错 然而,我发现的最接近的类似问题是,我无法弄清楚如何更改XAML中的数据路径,或者如何使INotifyPropertyChanged正常工作 请注意,Backgr

我目前正在学习WPF、数据上下文和数据绑定。我的目标是有一个任务栏任务(使用NotifyIconWpf),它有一个在后台运行的连续线程来监视网络

我已设法将UI元素(如屏幕截图所示)绑定到ProgramClock类,但它不会在ProgramClock更改时更新,很可能是因为INotifyPropertyChanged参数中的某些内容出错

然而,我发现的最接近的类似问题是,我无法弄清楚如何更改XAML中的数据路径,或者如何使INotifyPropertyChanged正常工作

请注意,BackgroundWorker线程成功地更新了应用程序的静态程序时钟(使用单独的WinForm检查),并且该时间最初加载到WPF中,因此可能是PropertyChanged没有被正确调用

程序时钟

public class ProgramClock : INotifyPropertyChanged
    {
        private DateTime _myTime;
        public event PropertyChangedEventHandler PropertyChanged;
        private ClockController clockController;

        public ProgramClock()
        {

            this._myTime = DateTime.Now;
            clockController = new ClockController();

            MessageBox.Show("created new clock");
        }

        public DateTime MyTime
        {
            get
            {
                return this._myTime;
            }

            set
            {
                if (_myTime == value) return;
                _myTime = value;

                //System.Windows.Forms.MessageBox.Show(PropertyChanged.ToString());
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(_myTime.ToString()));
            }
        }

        public string MyTimeString
        {
            get { return this._myTime.ToString(); }
        }

        public void UpdateTime()
        {
            this.MyTime = DateTime.Now;
        }
    }
气泡CS

public partial class InfoBubble : System.Windows.Controls.UserControl
{

    public InfoBubble()
    {
        InitializeComponent();
        this.DataContext = App.ClockBindingContainer;
    }
}
气泡XAML

<UserControl x:Class="FileWatcher.Controls.InfoBubble"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008">
    <Border
        Background="White"
        BorderBrush="Orange"
        BorderThickness="2"
        CornerRadius="4"
        Opacity="1"
        Width="160"
        Height="40">
            <TextBlock
          Text="{Binding Path=MyTimeString}"
          HorizontalAlignment="Center"
          VerticalAlignment="Center" />
    </Border>
</UserControl>

一个问题是调用
PropertyChanged
事件。您需要将正在更改的属性的名称传递给
PropertyChangedEventArgs
而不是新值

因此,请使用:

if (PropertyChanged != null)
    PropertyChanged(this, new PropertyChangedEventArgs("MyTime"));
而不是:

if (PropertyChanged != null)
    PropertyChanged(this, new PropertyChangedEventArgs(_myTime.ToString()));
但是,您实际上是绑定到另一个属性-
MyTimeString

最终,您绑定到的属性需要引发事件

   if (PropertyChanged != null)
       PropertyChanged(this, new PropertyChangedEventArgs(_myTime.ToString()));
您应该传递属性名称:

   if (PropertyChanged != null)
       PropertyChanged(this, new PropertyChangedEventArgs("MyTime");
不过,我建议您使用PostSharp库—它有一些很好的功能,可以让您编写普通属性,并通过自动提升
PropertyChanged
来“按属性装饰它”。如果您不想使用
PostSharp
至少创建一些方法,如:

public void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
     if (PropertyChanged != null)
         PropertyChanged(this, new PropertyChangedEventArgs(propertyName);
}

把它叫进你的塞特。(
[CallerMemberName]
是C#5.0功能,它自动传递“调用者”名称(在setter中它将传递属性名称)

您没有通知要绑定的属性(即
MyTimeString
)中的更改,所以WPF知道
MyTime
更改,但是
MyTimeString
也更改了吗?从未收到通知

尝试更改此选项:

            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(_myTime.ToString()));
为此:

            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("MyTimeString")); // Not MyTime!

感谢您的快速响应。但是,这并没有解决问题。:(用户界面的数据绑定仍然没有得到更新。@SpaceSteak每当您在WPF中有绑定问题时,请检查VS中的输出窗口(在“视图”菜单中查找)。如果有任何错误,将在那里提及。有什么问题吗?@SpaceSteak是否更改了文本=”{Binding Path=MyTimeString}到Text=“{Binding Path=MyTime}”?没有对PropertyChanged(..“MyTimeString”)的调用所以它显然不会更新。这很有效,@Fex.谢谢!:D自从我将App设置为datacontext以来,我在App类中使用了MyTimeString,但显然这不是正确的方法。我会将您的其他答案标记为已接受。@SpaceSteak为什么这不是答案?O_oThanks感谢您的快速响应。我尝试将属性更改转移到它自己的乐趣中操作并将其更改为“MyTime”,但它仍然不起作用。在VS2010上,因此没有C#5.0。@开始调试应用程序,单击“查看、输出”并检查是否存在任何绑定错误-如果存在,请将其写入此处
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("MyTimeString")); // Not MyTime!