WPF Xaml GridView SelectionChanged行为

时间:2016-08-12 00:44:05

标签: wpf xaml mvvm prism

我正在使用Prism.MVVM的WPF视图,它允许我们的用户编辑记录。 最初要编辑的记录是通过ComboBox选择的。

<ComboBox IsSynchronizedWithCurrentItem="True" 
          ItemsSource="{Binding Records}"                 
          SelectedItem="{Binding SelectedRecord}"/>

这很有用,但是用户想要一种更有效的方法来查找哪些记录包含需要更新的字段,因此我们添加了一个只读的DataGrid,他们可以对它们进行排序并直观地发现他们感兴趣的记录。接下来他们想要选择记录以编辑网格(但保留组合框)。这是出问题的地方。

理想情况下,我们正在寻找的行为是:

  • 如果用户从组合框中选择一条记录:

    1. 所选记录以
    2. 格式加载
    3. 所选记录在组合框中显示为已选中。
    4. 所选记录在网格中显示为已选中。
  • 如果用户在网格中选择记录

    1. 单击以选择记录。
    2. 所选记录以
    3. 格式加载
    4. 所选记录在组合框中显示为已选中
    5. 所选记录在网格中显示为已选中。

最成功的尝试

在DataGrid的SelectionChanged事件上触发命令

<DataGrid x:Name="TheDataGrid"
          ItemsSource="{Binding Source={StaticResource GridRecords}}"
          SelectedItem="DataContext.SelectedRecord, ElementName=LayoutRoot, Mode=OneWay}">
...
<i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
        <i:InvokeCommandAction CommandParameter="{Binding SelectedItem, ElementName=TheDataGrid}"
                               Command="{Binding DataContext.SelectRecordFromGridCommand, ElementName=LayoutRoot}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

DelegateCommand:

Public ReadOnly Property SelectRecordFromGridCommand As DelegateCommand(Of TheRecordType) = new DelegateCommand(Of TheRecordType)(Sub(r) SelectedRecord = r)

尝试使用SelectedItem绑定模式的各种选项。 如果删除了DataGrid SelectedItem绑定,我们得到1,2,4,5,6和7.但是从组合框中选择记录将不会显示在网格中选择的记录。

如果DataGrid SelectedItem绑定设置为OneWay,则通过组合框选择记录会中断:设置SelectedRecord会触发DataGrid中的SelectionChanged事件,该事件使用之前的值事件并有效地将一切恢复到原始值。

可以通过在ViewModel中的属性集上引入一个sentinal来解决这个问题

Private _selectedRecord As TheRecordType
Private _enableRecordSelection As Boolean = true
Public Property SelectedRecord As TheRecordType
    Get
        Return _selectedRecord 
    End Get
    Set(value As TheRecordType)
        If _enableRecordSelection 
            _enableRecordSelection = false
            SetProperty(_selectedRecord , value)
            _enableRecordSelection = true
        End If            
    End Set
End Property

这实际上是有效的,我们在写这个问题时提出了它,但感觉非常hacky。我的直觉告诉我必须有一个更好的方式,所以我还在问:

是否有干净的(最好是仅限xaml)方式进行设置?

我们尝试的其他最成功的事情:

具有TwoWay绑定的DataGrid的直接xaml配置

<DataGrid x:Name="TheDataGrid"
          ItemsSource="{Binding Source={StaticResource GridRecords}}"
          SelectedItem="DataContext.SelectedRecord, ElementName=LayoutRoot, Mode=TwoWay}"/>

有了这个,我们满足要求1到6;但是,当通过网格选择记录时,前一条记录始终会突出显示而不是当前记录。

DataGrid.InputBindings

<DataGrid.InputBindings>
    <MouseBinding Gesture="LeftClick"
                  CommandParameter="{Binding SelectedItem, ElementName=TheDataGrid}"
                  Command="{Binding DataContext.SelectRecordFromGridCommand, ElementName=LayoutRoot}"/>
</DataGrid.InputBindings>

没有SelectedItem绑定,这与InteractionTrigger上的无绑定SelectionChanged的行为类似,但它要求用户执行多个鼠标操作。第一次单击选择网格中的行(实际的粗体蓝色选择)第二次单击会触发命令。

OneWay上绑定SelectedItem时,此行为与直接xaml配置类似,但需要多次点击。

再次重申这个问题: 有没有更简洁的方法来完成7个要求而不是求助于属性设置器上的sentinal值?

0 个答案:

没有答案