我有一个文本块:
<TextBlock HorizontalAlignment="Left" Name="StatusText" Margin="0,20" TextWrapping="Wrap" Text="{Binding StatusText}">
... Status ...
</TextBlock>
隐藏代码:
public StatusPage()
{
InitializeComponent();
this.DataContext = new StatusPageViewModel(this);
}
在 viewModel 中:
private string _statusText;
/// <summary>
/// Status text
/// </summary>
public string StatusText
{
get { return _statusText; }
set { _statusText = value; }
}
并在 viewModel 中的函数中:
string statusText = Status.GetStatusText();
this.StatusText = statusText;
GetStatusText()
返回“工作完成”等字符串。该函数的值被分配给 this.StatusText
,但 TextBlock 的文本属性不会更改,并且仍显示占位符“... Status...”
我知道这样的问题 --> 点击<--- but after reading this I'm still not able to find solution
@更新
根据您的建议,我更新了我的代码,现在我有了这个:
public string StatusText
{
get
{
return _statusText;
}
set
{
_statusText = value;
RaisePropertyChanged("StatusText");
}
}
和viewModel的声明:
public class StatusPageViewModel : ObservableObject, INavigable
地点:
ObservableObject 类是:
public abstract class ObservableObject : INotifyPropertyChanged
{
#region INotifyPropertyChanged Members
/// <summary>
/// Raises the PropertyChange event for the property specified
/// </summary>
/// <param name="propertyName">Property name to update. Is case-sensitive.</param>
public virtual void RaisePropertyChanged(string propertyName)
{
OnPropertyChanged(propertyName);
}
/// <summary>
/// Raised when a property on this object has a new value.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
/// <param name="propertyName">The property that has a new value.</param>
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
#endregion // INotifyPropertyChanged Members
}
但是还是不行
您需要在 ViewModel 订单中实现
INotifyPropertyChanged
来通知 View 属性已更改。
这里是 MSDN 页面的链接:System.ComponentModel.INotifyPropertyChanged
最需要注意的是,您应该在属性设置器中引发
PropertyChanged
事件。
添加两种方式的绑定模式,因为默认情况下Textblock的绑定模式是一种方式
<TextBlock HorizontalAlignment="Left" Name="StatusText" Margin="0,20" TextWrapping="Wrap" Text="{Binding StatusText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
... Status ...
</TextBlock>
当然,您还需要实现 INotifyPropertyChanged 来实现此目的,请参阅 此链接 了解如何实现。
使用数据模型时,您必须确保模型在初始加载时完整。因此,如果您这样做: this.DataContext = mainViewModel 并且 mainViewModel 的某些部分未加载(=null),那么您将无法绑定它们。例如,我有一个模型,该模型中有一个对象程序。我将 TextBlock 的文本绑定到 Model.Program.Name。程序对象在初始加载时未连接,因此您必须在之后重新绑定到加载的对象,否则无法发送通知。
你的视图模型需要实现
INotifyPropertyChanged
,并且每次你的属性之一发生变化时(即在setter中),你都需要引发它。
没有它,WPF 就无法知道属性已更改。
我遇到了这个问题,这就是我做错的事情......
注意:我的 INotifyPropertyChanged 编码正确。
在我看来,我有
<SomeView.DataContext>
<SomeViewModel/>
<SomeView.DataContext/>
...这会调用 VM 的构造函数(创建一个指向/绑定的实例)。
在另一个类中(在我的程序主窗口的 ViewModel 代码中)我还实例化了 ViewModel,即:
private SomeAstractBaseViewModel someViewModel = new SomeViewModel();
private SomeAstractBaseViewModel someOtherViewModel = new SomeOtherViewModel();
它们都继承自超类,并且我在主窗口的一部分中显示不同视图的实例之间来回切换 - 按照我的意图。
如何连接所有这些是另一个问题,但是当我删除之前实例化 ViewModel 的另一个“未使用”实例的有问题的 xaml (在本答案的顶部)时,视图将按照 进行更新INotifyPropertyChanged机制。
在我的情况下,
UserControl
嵌套在View
中,当我尝试对Binding
中的属性使用UserControl
时,框架正在寻找ViewModel
中不存在的属性。为了解决这个问题,我必须指定 ElementName
。
MyControl.xaml:
<UserControl
...
x:Name="MyUserControl">
...
<Label Content="{Binding MyProperty, ElementName=MyUserControl}"
...
MyControl.xaml.cs:
public partial class MyControl: UserControl, INotifyPropertyChanged
{
...
private string _myProperty = "";
public string MyProperty
{
get => _myProperty ;
set
{
if (value == _myProperty ) return;
_myProperty = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
...
当您调用 OnPropertyChanged 时,请确保包含属性名称。今天花了我几个小时,这个他妈的隐藏的绑定魔法太令人沮丧了。给我一条错误消息或其他信息,而不是只是默默地失败!
因此,不要只调用 OnPropertyChanged() 而不提供参数,而是在属性设置器中调用它(这样 CallerMemberName 会为您填写),或者自己提供它。
例如在 xaml 中的某处您有绑定:
... Value="{Binding Progress}" ...
然后在代码隐藏中,您拥有继承自 INotifyPropertyChanged 的 DataContext 对象,并在更新您调用的值后的某个方法中:
OnPropertyChanged("Progress");
就我而言,问题是当我拨打
OnPropertyChanged
时。我输入的会员名不正确。例如:
不正确
private Student std = new Student();
public Student Std {
get { return std; }
set { std = value; OnPropertyChanged("Student"); }
}
正确
private Student std = new Student();
public Student Std {
get { return std; }
set { std = value; OnPropertyChanged("Std"); }
}
这里我必须传递属性名称而不是类名称
我也有类似的情况。我有一个带有实现 IPropertyChanged 的 ViewModel 的 WPF UserControl,看起来我做的一切都是正确的,除了一件事:我的代码在主线程上运行,而我的长时间运行的操作正在阻止 UI 的更新。
所以就我而言,我将 WindowControl.Dispatcher 放入我的 ViewModel 中,所以我必须做的事情是:
dispatcher.Invoke(() =>
{
Status = $"Processing task {number} of {total}.";
});
调度程序用于在 UI 线程上运行代码。