【问题标题】:WPF ListBox select next item after deletion with ICommandWPF ListBox 在使用 ICommand 删除后选择下一项
【发布时间】:2015-05-19 11:41:21
【问题描述】:

这个问题与this question 类似,但它涉及我面临的另一个问题,因为我使用了绑定。

我添加了一个按钮,用于从ListBox 中删除当前选定的项目(以及一个用于出现相同问题的DataGrid)。执行此操作的代码通过ICommand-object 和Button.Command 属性绑定到按钮:

<Button Command="{Binding DeleteRowCommand}"
        CommandParameter="{Binding ElementName=MyListBox, Path=SelectedItem}" />

但是这意味着点击动作是直接进入 ViewModel 的,当然 ViewModel 不知道视图的ListBox,所以它不能通知视图或更新任何选择。

在视图模型视图中触发代码隐藏的正确方法是什么?

也许我可以使用命令属性和Handles 语句,但我不确定这是否可行。

【问题讨论】:

    标签: wpf xaml mvvm datagrid listbox


    【解决方案1】:

    这就是我要做的。

    在您的 ViewModel 中创建一个属性来保存 SelectedItem。

    private YourTypeHere _SelectedThing;
    
    public YourTypeHere SelectedThing 
    {
       get { return _SelectedThing; }
       set 
       { 
          _SelectedThing = value;
    
          //Call INotifyPropertyChanged stuff
        }
    }
    

    现在,将 List 的 SelectedItem 绑定到此属性:

    <ListBox SelectedItem="{Binding SelectedThing}" ... />
    

    执行这些操作意味着您的SelectedThing 现在由 ViewModel 负责,并且当您调用 Delete 命令时,您可以简单地将 SelectedThing 属性更新为列表中的最后一项,然后您的 ListBox 将自动更新。

    【讨论】:

    • 这实际上是一种相当不错的处理方式。我将尝试用这种方法实现我的视图/视图模型,并告诉你我是否遇到任何困难。如果没有,我也会将此标记为已接受的答案。
    • 我有点挣扎,但方法是要走的路。我稍后会发布完整的解决方案。
    【解决方案2】:

    XAML:

    <ListBox DataContext="{Binding Path=Category, Mode=OneTime}"
             ItemsSource="{Binding Path=Fields}"
             SelectedItem="{Binding Path=SelectedItem, Mode=OneWay}"
             SelectedIndex="{Binding Path=SelectedIndex}" />
    

    CategoryViewModel 中的代码,来自数据上下文的 Category 对象的类:

    Public ReadOnly Property Fields As ObservableCollection(Of FieldViewModel)
      Get
        Return m_Fields
      End Get
    End Property
    Private ReadOnly m_Fields As New ObservableCollection(Of FieldViewModel)
    
    Public Property SelectedIndex As Integer
      Get
        Return m_SelectedIndex
      End Get
      Set(value As Integer)
        m_SelectedIndex = value
        ValidateSelectedIndex()
        RaisePropertyChanged("SelectedIndex")
        RaisePropertyChanged("SelectedItem")
      End Set
    End Property
    Private m_SelectedIndex As Integer = -1
    
    Public ReadOnly Property SelectedItem As FieldViewModel
      Get
        Return If(m_SelectedIndex = -1, Nothing, m_Fields.Item(m_SelectedIndex))
      End Get
    End Property
    
    Private Sub ValidateSelectedIndex()
      Dim count = m_Fields.Count
      Dim newIndex As Integer = m_SelectedIndex
    
      If count = 0 Then
        ' No Items => no selections
        newIndex = -1
      ElseIf count <= m_SelectedIndex Then
        ' Index > max index => correction
        newIndex = count - 1
      ElseIf m_SelectedIndex < 0 Then
        ' Index < min index => correction
        newIndex = 0
      End If
    
      m_SelectedIndex = newIndex
      RaisePropertyChanged("SelectedIndex")
      RaisePropertyChanged("SelectedItem")
    End Sub
    
    Public Sub New(model As Category)
      ' [...] Initialising of the view model,
      ' especially the m_Fields collection
    
      ' Auto update of SelectedIndex after modification
      AddHandler m_Fields.CollectionChanged, Sub() ValidateSelectedIndex()
      ' Set the SelectedIndex to 0 if there are items
      ' or -1 if there are none
      ValidateSelectedIndex()
    End Sub
    

    现在,每当您从 m_Fields 集合中删除一个项目时,SelectedItem 将更改为下一个项目,或者如果最后一个项目被删除,则为上一个项目,或者Nothing 如果最后一个剩余项目是删除。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多