【问题标题】:WPF data binding setter loop?WPF数据绑定设置器循环?
【发布时间】:2013-12-10 10:35:27
【问题描述】:

背景

我有一个包含ParentViewModel 项目的列表框:

<listBox x:Name="lstParentItems"
         ItemsSource="{Binding ParentItems}"
         SelectedItem={Binding SelectedParent, Mode=OneWayToSource}">
</ListBox>

每个父实例都有一个子项列表:ObservableCollection&lt;ChildViewModel&gt; ChildItems。当我选择一个父项时,我会在另一个列表框中显示子项列表:

<!-- displays a list of ChildViewModels for currently selected ParentViewModel -->
<ListBox x:Name="lstChildItems" DataContext={Binding SelectedParent}"
         ItemsSource="{Binding ChildItems}"
         SelectedItem="{Binding SelectedChild, Mode=OneWayToSource}"
         SelectionChanged="lstChildItems_SelectionChanged"
         MouseDoubleClick="lstChildItems_MouseDoubleClick">
</ListBox>

如您所见,我希望 Parent 实例知道当前选择了哪个 Child。

问题

在调试一个不同的错误时,我发现了一个奇怪的行为,某种 setter 循环。我在 SelectedChild 设置器中设置了一个调试断点,如下所示:

public ChildViewModel SelectedChild {
    get { return _selectedChild; }
    set {
        _selectedChild = value;
        RaisePropertyChanged("SelectedChild");
    }
}

当我选择一个子项时,setter 不会调用一次,而是一遍又一遍地执行。 调试器在断点处(RaisePropertyChanged 行)一直暂停,单击 Continue 后立即暂停又在同一个地方。

我不知道这种行为是从哪里来的。任何想法从哪里开始寻找? 我很乐意提供任何所需的详细信息。到目前为止,我应该提一下:

  • SelectedChild 属性不参与任何其他绑定(XAML 或代码)
  • SelectedChild从未在代码中分配给
  • ChildViewModel 我有一个CanCommandExecute 方法来检查SelectedChild != null
  • lstChildItems 中的代码隐藏事件处理程序用于与难以直接合并到我的 MVVM 架构中的 COM 控件进行交互;他们所做的只是阅读有关SelectedChild 的一些信息(如果它不为空);没有分配

【问题讨论】:

  • 您如何在父项更改时填写 ChildItems?
  • lstParents ListBox 中显示的每个父级都已经在内存中拥有一个子级列表。选定的父项更改不会发生“填充”。
  • 你不应该从你的设置器中调用RaisePropertyChanged,除非值实际上改变了,顺便说一句。

标签: .net wpf data-binding infinite-loop


【解决方案1】:

你的一个要点就是你的答案:

• 在 ChildViewModel 中,我有一个 CanCommandExecute 方法来检查 SelectedChild 是否为 != null

无非就是CanCommandExecute 方法反复调用你的SelectedChild 属性。每次 UI 获得或失去焦点时都会调用它,包括每次按 F5 继续。

当我的应用程序运行时,我实际上在需要时使用此方法在我的视图模型中执行...只需在我的ICommandCanExecute 部分放置一个断点并返回 UI并且断点立即被击中......非常有用......一旦你知道发生了什么。

【讨论】:

  • 这听起来像是一个很好的解释,但不幸的是,事实并非如此 :( 我在 CanCommandExecute 中注释掉了 null 检查,并将其更改为 return true;,但行为仍然相同. 另外,为什么它会调用setter,而不仅仅是getter?
  • 这很好...然后在您的Entire Solution 中搜索'SelectedChild = '...您的查找结果之一必须被调用。注释掉每一个,直到你找到有问题的行,然后你就可以找出它被调用的原因。我仍然认为这听起来与 CanCommandExecute 方法有关。
  • 搜索了整个解决方案。没有。除了一个 XAML 绑定之外,我只读取该值几次,但从未分配给它。
  • @oli.G... 那么解决方案是什么?
  • 你是对的,这是关于 UI 获得和失去焦点。我还弄清楚了为什么调用 SETTER - 当 UI 失去焦点时,即使我选择了一个项目,框架显然也会将其设置为 null。当 UI 再次获得焦点时,所选项目将设置为其原始值。我是通过使用 MessageBox 而不是断点发现的。好老的该死的 MessageBox 有时真的胜过任何调试器和日志记录 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-25
  • 2013-02-18
  • 2010-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多