WPF MVVM Light多个ListBoxItem绑定到同一个对象

时间:2016-12-07 16:30:54

标签: c# wpf mvvm listbox

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

我遇到的情况是:

  1. 用户从ItemsControlItemA中选择ListBoxItemA,PropertyChanged触发,SelectedClass对象设置为正确的值。
  2. 用户然后从ItemsControlItemB中选择ListBoxItemA,PropertyChanged触发,将SelectedClass对象设置为正确的值。
  3. 用户然后从ItemsControlItemA中选择ListBoxItemA,但由于该列表中的选择仍被认为是步骤1中的相同项,因此PropertyChanged不会触发,而SelectedClass对象仍然是来自ItemsControlItemB的ListListItemA。
  4. 所以我的问题是,如何让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>
    

    编辑:为了便于阅读,清理了一些示例。

1 个答案:

答案 0 :(得分:0)

您可以处理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控件在您选择新项目时为您设置的相同视图模型源属性。此功能属于视图或控件。