我是Silverlight新手,我不能让简单的Silverlight绑定示例工作!
我需要创建一个视图模型,它在加载时显示列表中的文档数。
我创建了一个实现INotifyPropertyChanged的基类:
public abstract class BaseViewModel : INotifyPropertyChanged {
protected BaseViewModel() {}
#region INotifyPropertyChanged Members
protected void OnPropertyChanged(string propertyName) {
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
我制作了一个具有“CountDocs”属性的子类:
public class DocumentViewModel : BaseViewModel {
public DocumentViewModel () {
...
}
...
public int CountDocs {
get { return countDocs; }
set {
if (countDocs != value) {
countDocs = value;
OnPropertyChanged("CountDocs");
}
}
}
public int countDocs;
}
我有DocumentViewModel.xaml,其中包含以下内容:
<UserControl
...
xmlns:vm="clr-namespace: ... .ViewModels" >
...
<UserControl.Resources>
<vm:DocumentViewModel x:Key="viewModel"/>
</UserControl.Resources>
...
<TextBlock x:Name="CounterTextBlock" Text="{Binding Source={StaticResource viewModel}, Path=CountDocs}"></TextBlock>
我提到了我的子类的命名空间,我使用键“viewModel”创建了我的子类的资源,并且我输入了textblock的绑定到此对象的属性“CountDocs”。
问题是CountDocs属性只填充TextBlock一次:加载时。但后来我设置了CountDocs,它没有填充TextBlock。
我曾尝试使用绑定的Mode属性来使用DataContext,但我仍然无法使其工作。
绑定有问题吗?如何更改对象的CountDocs属性时更新ViewModel?
由于
答案 0 :(得分:0)
如果我了解您的问题的详细信息,您可能正在更新后台线程上的UI绑定值(作为文档加载)。
您需要在UI线程上进行此操作,否则更改将不可见。在我们的一个WPF应用程序中,随机更新消失,直到我们意识到这一点。
我们在Silverlight(和WPF)应用程序中做了很多多线程,所以为了避免这个问题,我们在一个基类中实现了我们的通知助手,如下所示(其他东西被修剪掉)。它在主UI线程上调度所有通知消息。试一试:
public class ViewModelBase : INotifyPropertyChanged
{
protected delegate void OnUiThreadDelegate();
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void SendPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
// Ensure property change is on the UI thread
this.OnUiThread(() => this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)));
}
}
protected void OnUiThread(OnUiThreadDelegate onUiThreadDelegate)
{
// Are we on the Dispatcher thread ?
if (Deployment.Current.Dispatcher.CheckAccess())
{
onUiThreadDelegate();
}
else
{
// We are not on the UI Dispatcher thread so invoke the call on it.
Deployment.Current.Dispatcher.BeginInvoke(onUiThreadDelegate);
}
}
}
答案 1 :(得分:0)
好了,因为您在XAML中创建了ViewModel实例,所以您需要访问并使用该ViewModel。
如果您有另一个实例,该实例将不会更新您的绑定。只会使用您的资源中创建的实例。
现在你说你设置了CountDocs属性,但我没有看到任何代码。无论如何,您必须使用资源中的ViewModel实例。
这就是为什么我喜欢在我的视图的构造函数中实例化我的视图模型并保留对它的引用。除非您计划将大量数据源附加到绑定,否则只需将LayoutRoot.DataContext设置为ViewModel实例并删除绑定中的Source属性。
ViewModelBase _vm = null;
public MyView()
{
_vm = new DocumentViewModel();
this.LayoutRoot.DataContext = _vm;
}
在XAML中,
<TextBlock x:Name="CounterTextBlock" Text="{Binding CountDocs}"></TextBlock>
答案 2 :(得分:0)
正如我们在您的问题的评论中发现的那样,您将ViewModel实例化了两次,并更改了实际上未绑定到视图的属性值。
怎么会这样?您要么使用MVVM框架自动将ViewModels连接到视图,要么它发生在您不知道的代码中。在构造函数中放置一个断点,当它命中时,在Visual Studio中分析调用堆栈。