C# WPF:未使用INotifyPropertyChanged更新UI
我目前正在学习WPF、数据上下文和数据绑定。我的目标是有一个任务栏任务(使用NotifyIconWpf),它有一个在后台运行的连续线程来监视网络 我已设法将UI元素(如屏幕截图所示)绑定到ProgramClock类,但它不会在ProgramClock更改时更新,很可能是因为INotifyPropertyChanged参数中的某些内容出错 然而,我发现的最接近的类似问题是,我无法弄清楚如何更改XAML中的数据路径,或者如何使INotifyPropertyChanged正常工作 请注意,BackgroundWorker线程成功地更新了应用程序的静态程序时钟(使用单独的WinForm检查),并且该时间最初加载到WPF中,因此可能是PropertyChanged没有被正确调用 程序时钟C# WPF:未使用INotifyPropertyChanged更新UI,c#,wpf,xaml,datacontext,C#,Wpf,Xaml,Datacontext,我目前正在学习WPF、数据上下文和数据绑定。我的目标是有一个任务栏任务(使用NotifyIconWpf),它有一个在后台运行的连续线程来监视网络 我已设法将UI元素(如屏幕截图所示)绑定到ProgramClock类,但它不会在ProgramClock更改时更新,很可能是因为INotifyPropertyChanged参数中的某些内容出错 然而,我发现的最接近的类似问题是,我无法弄清楚如何更改XAML中的数据路径,或者如何使INotifyPropertyChanged正常工作 请注意,Backgr
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!