C#WPF InotifyProperty已更改,未更新表单
我试图实现一个表单,其中包含一些基于用户输入的计算。使用MVVM模式,特别是INotifyPropertyChanged 当用户在文本框中输入一个值,计算例程启动,表单更新结果时,所有这些都可以正常工作 但是,当输入从codebehind更改时,Inotify例程启动,计算完成,但绑定控件不更新 我有两个问题:C#WPF InotifyProperty已更改,未更新表单,c#,wpf,inotifypropertychanged,C#,Wpf,Inotifypropertychanged,我试图实现一个表单,其中包含一些基于用户输入的计算。使用MVVM模式,特别是INotifyPropertyChanged 当用户在文本框中输入一个值,计算例程启动,表单更新结果时,所有这些都可以正常工作 但是,当输入从codebehind更改时,Inotify例程启动,计算完成,但绑定控件不更新 我有两个问题: 使用框架内的页面,我希望在页面更改时触发刷新 导入以前保存在Xml文件中的数据。同样,例程会激发,但不会更新窗体的绑定控件 我附上了代码的浓缩版本,但我认为这并不是问题所在。注意,我使用
//INotify code
using s = Calc.Models.GlobalStrings;
namespace Calc.ViewModels.INotify
{
public class UcIOChanged : INotifyPropertyChanged
{
private static UcIOChanged instance;
public UcIOChanged() { }
//Make the class is a singleton
public static UcIOChanged Instance
{
get
{
if (instance == null)
{
instance = new UcIOChanged();
}
return instance;
}
}
public event PropertyChangedEventHandler PropertyChanged;
public string Pressure
{
get
{
return s.Pressure;
}
set
{
s.Pressure = value; OnPropertyChanged();
}
}
public void OnPropertyChanged()
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Pressure)));
}
}
}
注意,我使用的是单例类
此代码中没有错误。
但您可能使用不正确。
为了避免意外的使用错误,我建议您更改实现:
public class UcIOChanged
{
// Hide the constructor to avoid
// accidentally creating other instances.
private UcIOChanged() {}
//Make the class is a singleton
public static UcIOChanged Instance { get; } = new UcIOChanged();
public string Pressure
{
get
{
return s.Pressure;
}
set
{
if (!Equals(s.Pressure, value))
{
s.Pressure = value;
PressureChanged?.Invoke(this, EventArgs.Empty);
}
}
}
// The event of the same name.
// It's easier for one or two properties
// than the INotifyPropertyChanged implementation.
public event EventHandler PressureChanged;
}
使用:
<TextBox Text="{Binding Pressure, Source={x:Static local:UcIOChanged.Instance}}"/>
p.S.如果您在代码中的某个位置更改S.Pressure
,而不是通过UcIOChanged.instance的实例更改,则正确的操作可能会受到影响。因此,您必须确保只有在通知该变量(属性或字段?)的更改后才能访问该变量。这可能会有所帮助。在绑定到Pressure属性的UI元素上,尝试以下更新SourceTrigger=PropertyChanged。。例如,请注意,
nameof(Pressure)
绝对不应位于OnPropertyChanged方法内。应该有一个字符串参数,并且应该像调用OnPropertyChanged(nameof(Pressure))一样调用该方法代码>@Saurav所说的不正确UpdateSourceTrigger=PropertyChanged
与INotifyPropertyChanged接口的PropertyChanged事件无关。它控制其他绑定方向(从目标到源)的工作方式,对单向绑定(仅从源到目标)没有任何影响。此外,当一个输入属性发生更改时,它会更新许多其他绑定结果,这在我提供的代码示例中没有显示。“这比INotifyPropertyChanged实现更容易…”对于多个属性来说可能不正确,因为您可以只编写PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(nameof(Pressure)))
而不是压力更改?.Invoke(this,EventArgs.Empty)
,但只声明一个事件,而不是每个属性声明一个事件。不需要OnPropertyChanged方法。当然,您必须声明接口实现。好吧,对于两个,它不是真的:-)错误不在类的实现中。如果您创建了多个UcIOChanged
实例,则可能会发生意外错误。这正是我在示例中展示的内容。使用另一个事件是次要的,并不重要。这只是补充信息。隐藏实例构造函数很重要。如果这没有帮助,那么我们需要弄清楚如何使用这个类。这需要一个再现问题的解决方案的最小示例。此外,请务必注意,在计算逻辑中,您应该始终仅通过UcIOChanged.Instance
实例访问s.Pressure
变量。要在XAML中获取实例,必须使用x:Static标记扩展。在我的示例中,请仔细查看如何获取绑定的源代码。也可以为数据上下文或某些其他属性获取它。