【问题标题】:WPF MVVM Light Multiple ListBoxItems bound to same objectWPF MVVM Light多个ListBoxItems绑定到同一个对象
【发布时间】:2016-12-07 16:30:54
【问题描述】:

我有包含程序生成的 ItemsControl 的 UserControl。 ItemsControl 中的每个项目都包含一个 ListBox,并且将生成多少个项目并没有一致的数量。列表框中的选中项绑定到 ViewModel 中的对象(SelectedClass)。 SelectedClass对象的初始值为null。

我遇到的情况是这样的:

  1. 用户从 ItemsControlItemA 中选择 ListBoxItemA,PropertyChanged 触发,SelectedClass 对象设置为正确的值。
  2. 然后用户从 ItemsControlItemB 中选择 ListBoxItemA,PropertyChanged 触发,SelectedClass 对象设置为正确的值。
  3. 然后用户从 ItemsControlItemA 中选择 ListBoxItemA,但由于该列表中的选择仍被认为是第 1 步中的相同项目,PropertyChanged 不会触发,并且 SelectedClass 对象仍然是来自 ItemsControlItemB 的ListBoxItemA。

所以我的问题是,我如何让 UpdateSourceTrigger 事件触发 OnClick 而不是在 PropertyChanged 上触发,这甚至是处理它的最佳方法吗?我正在使用 MVVM Light 框架。

谢谢

<ItemsControl ItemsSource="{Binding AllUpcomingClasses}" >
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding classDescription}" />                    
                <ListBox Name="availableClasses"
                    ItemsSource="{Binding ClassInstances}" 
                    SelectedItem="{Binding
                                       DataContext.SelectedClass, 
                                       Mode=TwoWay}
                                       RelativeSource={RelativeSource 
                                           FindAncestor, 
                                           AncestorType={x:Type UserControl}}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <Grid>
                                    <TextBlock Text="{Binding ClassDate}" />
                                </Grid>
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>                                    
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

编辑:为了便于阅读,稍微整理了示例。

【问题讨论】:

  • 我想你这里有一个 x/y,但我不确定。一个最小的例子肯定会有所帮助(例如,重现问题所需的最小 XAML 和代码,没有像样式和模板这样无关紧要的东西)。 ItemsSource/SelectedItem 绑定对与对象实例相关的问题特别敏感,但我不知道这是否是这里的问题。要尝试的另一件事是在所有 SelectedClass 绑定上指定 TwoWay 模式。
  • 为你清理了一下。双向模式已设置。
  • 欣赏,现在检查 this 编辑。代码清晰可帮助您更快地获得更好的答案。拥有sscce 更多的是我在谈论的内容。
  • 听起来你的ListBoxes 应该处理GotFocus event 因此设置SelectedItem 他们第一次获得焦点。之后,选择器将处理更改。 HTH

标签: c# wpf mvvm listbox


【解决方案1】:

您可以处理 ListBoxItem 容器的 PreviewMouseLeftButtonDown 事件,并“手动”设置您的视图模型的 SelectedItem 属性,如果单击的项目是已选择的项目:

<ListBox SelectedItem="{Binding SelectedItem}" xmlns:s="clr-namespace:System;assembly=mscorlib">
  <ListBox.ItemContainerStyle>
     <Style TargetType="ListBoxItem">
        <EventSetter Event="PreviewMouseLeftButtonDown" Handler="OnMouseLeftButtonDown"/>
     </Style>
  </ListBox.ItemContainerStyle>
  <s:String>A</s:String>
  <s:String>B</s:String>
  <s:String>C</s:String>
</ListBox>



private void OnMouseLeftButtonDown(object sender, MouseEventArgs e)
{
  ListBoxItem lbi = sender as ListBoxItem;
  if (lbi != null)
  {
    YourViewModel vm = DataContext as YourViewModel;
    if (vm != null)
    {
        var selectedItem = lbi.DataContext as YourObjectType;
        if (vm.SelectedItem == selectedItem)
        {
            vm.SelectedItem = selectedItem;
            e.Handled = false;
        }
    }
  }
}

如果您不想在视图的代码隐藏中处理此问题,您可以将相同的功能包装在附加的行为中:https://www.codeproject.com/articles/28959/introduction-to-attached-behaviors-in-wpf。前一种方法并没有真正打破 MVVM 模式,因为您只是在“扩展”ListBox 控件功能,以便能够设置与 ListBox 控件在您选择新项目时为您设置的相同视图模型源属性。此功能属于视图或控件。

【讨论】:

  • 虽然我在处理程序中使用了不同的代码,但 PreviewLeftMouseButtonDown 让我走上了正确的道路。
猜你喜欢
  • 2013-06-04
  • 1970-01-01
  • 2010-12-31
  • 1970-01-01
  • 1970-01-01
  • 2017-11-08
  • 2020-04-01
  • 2023-03-15
  • 2013-06-01
相关资源
最近更新 更多