【问题标题】:Silverlight binding does not work dynamicallySilverlight 绑定不能动态工作
【发布时间】:2012-08-14 08:51:27
【问题描述】:

我是 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”创建了我的子类的资源,并输入了文本块的绑定,到这个对象的属性“CountDocs”。

问题在于 CountDocs 属性仅填充 TextBlock 一次:加载时。但后来我设置了 CountDocs,它并没有填充 TextBlock。

我尝试过使用绑定的Mode属性,来使用DataContext,但还是不行。

绑定有问题吗?当我的对象的 CountDocs 属性更改时,如何使 ViewModel 更新?

谢谢

【问题讨论】:

  • 您是否检查过它是否通过了handler != null 条件并引发了事件?
  • VS 中的“输出”窗口会显示绑定失败。我必须查看更多代码,但可能的远程诊断是您不小心创建了多个 DocumentViewModel 实例。
  • 您是否尝试在另一个线程上设置新值?任何 UI 属性更新都必须在 UI 线程上进行(例如,您需要使用调度程序将它们传递给 UI 线程)。如果是这样,下面为您提供可能的答案。
  • @herzmeister:我想你是对的,因为有两个构造函数:默认和带参数。删除带参数的构造函数会导致错误。需要什么样的代码?我怎么能创建几个对象?这是一个常见的错误吗?
  • 用你的调试器在构造函数中放置一个断点,看看它在哪里被实例化。也许您使用的框架会自动连接视图模型并将您的视图绑定到错误的实例,或者您不小心在其他地方留下了一段代码。

标签: silverlight binding


【解决方案1】:

好的,因为您在 XAML 中创建了 ViewModel 实例,您需要访问和使用该 ViewModel。

如果您有另一个实例,该实例不会更新您的绑定。只会使用在您的资源中创建的实例。

现在您说您设置了 CountDocs 属性,但我没有看到任何代码。无论您在哪里执行此操作,都必须使用资源中的 ViewModel 实例。

这就是为什么我喜欢在我的视图的构造函数中实例化我的视图模型并保留对它的引用。此外,除非您计划将许多数据源附加到您的绑定,否则您可以简单地将 LayoutRoot.DataContext 设置为您的 ViewModel 实例并删除绑定中的 Source 属性。

ViewModelBase _vm = null;
公共 MyView()
{
_vm = new DocumentViewModel();
this.LayoutRoot.DataContext = _vm;
}

在 XAML 中, &lt;TextBlock x:Name="CounterTextBlock" Text="{Binding CountDocs}"&gt;&lt;/TextBlock&gt;

【讨论】:

  • 在他给出的示例中,他在 XAML 中实例化了 VM,并直接正确地将其引用为 Binding 源:Source={StaticResource viewModel}
【解决方案2】:

如果我了解您的问题的详细信息,您可能正在后台线程上更新 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);
        }
    }
}

【讨论】:

  • @Roux:你能发布你用来更新属性的代码吗?
【解决方案3】:

正如我们在您的问题的 cmets 中发现的那样,您的 ViewModel 实例化了两次,并更改了实际未绑定到视图的视图模型的属性值。

怎么可能?您要么使用 MVVM 框架将 ViewModels 自动连接到 Views,要么它发生在您不知道的代码中的某个地方。在构造函数中放置一个断点,当它命中时,在 Visual Studio 中分析调用堆栈。

【讨论】:

    猜你喜欢
    • 2010-09-26
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 2012-01-17
    • 1970-01-01
    • 2011-04-13
    • 2011-05-11
    • 1970-01-01
    相关资源
    最近更新 更多