C# 使用UpdateSourceTrigger=PropertyChanged更新WPF时出现问题
首先(完全公开),我是C#的相对初学者,所以这可能是一个明显的oops。我已经在stackoverflow上复习了几十个类似的问题和例子,但我仍然无法找出我做错了什么。我从VS 2017 WPFapp项目开始。更改了启动,以便我可以手动加载窗口。创建了一个带有递增值计时器的类,然后使用INotifyPropertyChanged更新我的主窗口上的文本框 WPF窗口加载良好。TextBlock以值5开始,因此绑定至少指向我的类和值。您将在输出中注意到,值正在随计时器事件更新,NotifyPropertyChanged正在触发,但TextBlock从未更改 我唯一的想法是TextBlock链接到了我的UpdateWPF类的错误实例,但我不明白这是怎么回事 提前感谢您的帮助 这是我的密码 MainWindow.xaml:(实际上刚刚删除了一个文本块并设置了绑定) App.xaml(刚刚注释掉了StartupUri) 和输出C# 使用UpdateSourceTrigger=PropertyChanged更新WPF时出现问题,c#,.net,wpf,xaml,C#,.net,Wpf,Xaml,首先(完全公开),我是C#的相对初学者,所以这可能是一个明显的oops。我已经在stackoverflow上复习了几十个类似的问题和例子,但我仍然无法找出我做错了什么。我从VS 2017 WPFapp项目开始。更改了启动,以便我可以手动加载窗口。创建了一个带有递增值计时器的类,然后使用INotifyPropertyChanged更新我的主窗口上的文本框 WPF窗口加载良好。TextBlock以值5开始,因此绑定至少指向我的类和值。您将在输出中注意到,值正在随计时器事件更新,NotifyPrope
Timer Event Fired. New Value is 6
NotifyPropertyChanged Fired.
Timer Event Fired. New Value is 7
NotifyPropertyChanged Fired.
Timer Event Fired. New Value is 8
NotifyPropertyChanged Fired.
Timer Event Fired. New Value is 9
NotifyPropertyChanged Fired.
Timer Event Fired. New Value is 10
NotifyPropertyChanged Fired.
Timer Event Fired. New Value is 11
NotifyPropertyChanged Fired.
正如上面的评论中所说,您必须正确设置
UpdateSourceTrigger
。我也不推荐您实现属性的方式。它们应该是这样的:
private int _value;
public int Value
{
get => _value;
set
{
_value = value;
OnPropertyChanged(nameof(Value));
}
}
现在你可以说Value=0
而不是手动引发属性更改
事件
如果将NotifyPropertyChanged
方法更改为:
private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgw(propertyName));
Console.WriteLine("NotifyPropertyChanged Fired.");
}
您不必将属性名称传递给NotifyPropertyChanged
。运行时将自动执行此操作,因为调用了CallerMemberNameAttribute
问候
洛里斯
编辑:
我的财产只是一个财产的例子,而不是你的。但是你只要改变类型,它就会工作
这应该适合您:
public class UpdateWPF : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
Console.WriteLine("NotifyPropertyChanged Fired.");
}
private int _value = 5;
public UpdateWPF()
{
Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 1000;
aTimer.Enabled = true;
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
var i = Convert.ToInt32(value);
Value = ++i;
}
public string Value
{
get => _value;
set
{
_value = value;
NotifyPropertyChanged();
}
}
}
正如上面的评论中所说,您必须正确设置
UpdateSourceTrigger
。我也不推荐您实现属性的方式。它们应该是这样的:
private int _value;
public int Value
{
get => _value;
set
{
_value = value;
OnPropertyChanged(nameof(Value));
}
}
现在你可以说Value=0
而不是手动引发属性更改
事件
如果将NotifyPropertyChanged
方法更改为:
private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgw(propertyName));
Console.WriteLine("NotifyPropertyChanged Fired.");
}
您不必将属性名称传递给NotifyPropertyChanged
。运行时将自动执行此操作,因为调用了CallerMemberNameAttribute
问候
洛里斯
编辑:
我的财产只是一个财产的例子,而不是你的。但是你只要改变类型,它就会工作
这应该适合您:
public class UpdateWPF : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
Console.WriteLine("NotifyPropertyChanged Fired.");
}
private int _value = 5;
public UpdateWPF()
{
Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 1000;
aTimer.Enabled = true;
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
var i = Convert.ToInt32(value);
Value = ++i;
}
public string Value
{
get => _value;
set
{
_value = value;
NotifyPropertyChanged();
}
}
}
ASh发现了我的问题,但他将其作为评论发布,所以我将回答这个问题。因为我已经解决了其他一些问题,所以我把它们都贴在这里 真正的问题出现在我的主窗口中。xaml
Text="{Binding Path=GetValue,Mode=OneTime,UpdateSourceTrigger=PropertyChanged}"
应该是
Text="{Binding Path=GetValue,Mode=OneWay}"
以后会变成
Text="{Binding Path=Value,Mode=OneWay}"
正如ASh指出的,UpdateSourceTrigger在本例中完全没有意义
Loris156指出了一些其他问题。有些建议是错误的,但我无意中发现了其中的优点,并得出了结论
命名约定
我来自java,所有的东西都在获取这个或设置这个,这个是变量。MS建议Value(){get;set;},Value为变量。loris156更喜欢_值,我看到很多人都这么做。碰巧“value”是一个非常糟糕的例子,因为它在自动属性设置器中使用。尽管如此,我还是坚持MS的方式,因为我使用的是他们的编译器 因此,我的getter/setter变成了“Value” 我还要指出,Lori156使用了int返回,但这对我使用的文本框不起作用 我以前无法使[CallerMemberName]正常工作。这也与我的能手/二传手有关。通过排除setter,我破坏了auto属性功能。看 正如我前面提到的,int getter不能使用文本框,所以我选择在setter中将字符串转换回int。这真的没关系,反正我也不会用。 下面是App.xaml.cs的代码更改
private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
Console.WriteLine("NotifyPropertyChanged Fired.");
}
如果有人有进一步的建议,我愿意接受 ASh发现了我的问题,但他将其作为评论发布,所以我将回答这个问题。因为我已经解决了其他一些问题,所以我把它们都贴在这里 真正的问题出现在我的主窗口中。xaml
Text="{Binding Path=GetValue,Mode=OneTime,UpdateSourceTrigger=PropertyChanged}"
应该是
Text="{Binding Path=GetValue,Mode=OneWay}"
以后会变成
Text="{Binding Path=Value,Mode=OneWay}"
正如ASh指出的,UpdateSourceTrigger在本例中完全没有意义
Loris156指出了一些其他问题。有些建议是错误的,但我无意中发现了其中的优点,并得出了结论
命名约定
我来自java,所有的东西都在获取这个或设置这个,这个是变量。MS建议Value(){get;set;},Value为变量。loris156更喜欢_值,我看到很多人都这么做。碰巧“value”是一个非常糟糕的例子,因为它在自动属性设置器中使用。尽管如此,我还是坚持MS的方式,因为我使用的是他们的编译器 因此,我的getter/setter变成了“Value” 我还要指出,Lori156使用了int返回,但这对我使用的文本框不起作用 我以前无法使[CallerMemberName]正常工作。这也与我的能手/二传手有关。通过排除setter,我破坏了auto属性功能。看 正如我前面提到的,int getter不能使用文本框,所以我选择在setter中将字符串转换回int。这真的没关系,反正我也不会用。 下面是App.xaml.cs的代码更改
private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
Console.WriteLine("NotifyPropertyChanged Fired.");
}
我开着