select 数据网格中包含分组数据的一行
select a row on datagrid that has grouped data
我在网上搜索过并亲自尝试过,但无法找到一种方法来准确地 select 记录编程,方法是在具有分组数据的数据网格上提供搜索值。下面的代码适用于未分组的数据,但是当数据被分组时,索引似乎不再有效并且分组似乎在数据的索引上。
这是表格的屏幕截图。数据已分组。用户输入销售订单号并单击查找按钮。我想记录为该行找到的要突出显示的内容。
这是找到记录时未分组的数据,可以看到高亮显示的记录:
下面是我的代码。单击“查找”按钮时会触发 OnSelectionButtonClick 事件。 cmdAddRemoveGroup_Click 过程中的数据是 grouped/ungrouped。数据在 RebindData 过程中绑定到网格。将销售订单传递到 SelectGridRow 过程以 select 一行(如果找到)。
感谢任何帮助!
谢谢,吉米
'Module level scope
Private da As wpfProductionDashboard.flexDataSetTableAdapters.vwProductionScheduleWPFMainTableAdapter = New wpfProductionDashboard.flexDataSetTableAdapters.vwProductionScheduleWPFMainTableAdapter()
Private Sub OnSelectionButtonClick(sender As Object, e As RoutedEventArgs)
Try
Dim so As Integer = Convert.ToInt32(Me.txtFind.Text)
Dim index As Integer = FlexDataSet.vwProductionScheduleWPFMain.Rows.IndexOf(FlexDataSet.vwProductionScheduleWPFMain.Rows.Find(so))
'Dim index2 As Integer = 1
'For Each c In FlexDataSet.vwProductionScheduleWPFMain.Rows
' If c(0) = so Then
' SelectGridRow(dataGrid1, index2)
' Exit Sub
' End If
' Console.WriteLine(c(0))
' index2 += 1
'Next
If index > 0 Then
Console.WriteLine(index.ToString())
SelectGridRow(dataGrid1, index)
End If
Catch ex As Exception
MessageBox.Show(ex.Message, "Find button click error", MessageBoxButton.OK, MessageBoxImage.Error)
End Try
End Sub
Private Sub SelectGridRow(ByVal DataGrid As DataGrid, ByVal rowIndex As Integer)
If Not DataGrid.SelectionUnit.Equals(DataGridSelectionUnit.FullRow) Then
Throw New ArgumentException("The SelectionUnit of the DataGrid must be set to FullRow.")
End If
If rowIndex < 0 OrElse rowIndex > (DataGrid.Items.Count - 1) Then
Throw New ArgumentException(String.Format("{0} is an invalid row index.", rowIndex))
End If
DataGrid.SelectedItems.Clear()
Dim item As Object = DataGrid.Items(rowIndex)
DataGrid.SelectedItem = item
Dim row As DataGridRow = TryCast(DataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex), DataGridRow)
If row Is Nothing Then
' bring the data item into view
DataGrid.ScrollIntoView(item)
row = TryCast(DataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex), DataGridRow)
End If
End Sub
Private Sub cmdAddRemoveGroup_Click(sender As Object, e As RoutedEventArgs) Handles cmdAddRemoveGroup.Click
Try
If cmdAddRemoveGroup.IsChecked = False Then
FlexDataSet.vwProductionScheduleWPFMain.DefaultView.RowFilter = "SalesOrderStatus <> 'Hold' and SalesOrderStatus <> 'Approval Done'"
vw.GroupDescriptions.Add(New PropertyGroupDescription("SalesOrderStatusGroup", New OpenStatusConverter))
Else
vw.GroupDescriptions.Clear()
End If
SortDataGrid()
Catch ex As Exception
MessageBox.Show(ex.Message, "Grouping Event", MessageBoxButton.OK, MessageBoxImage.Error)
End Try
End Sub
Private Sub RebindData()
Try
Dim taStatuses As wpfProductionDashboard.flexDataSetTableAdapters.spGetProductionDashboardStatusesTableAdapter = New wpfProductionDashboard.flexDataSetTableAdapters.spGetProductionDashboardStatusesTableAdapter()
da.Fill(FlexDataSet.vwProductionScheduleWPFMain)
taStatuses.Fill(FlexDataSet.spGetProductionDashboardStatuses)
vw.View.MoveCurrentToFirst()
cvOrderStatuses.View.MoveCurrentToFirst()
lstOrderStatus.ItemsSource = cvOrderStatuses.View
Catch ex As Exception
MessageBox.Show(ex.Message, "Rebind Data Event", MessageBoxButton.OK, MessageBoxImage.Error)
End Try
End Sub
谢谢康斯坦丁。我怕你会这么说。我还没有想出如何实现 ObservableCollection,因为这个应用程序不使用 MVVM。如果您不介意,而且我理解您是否介意或不想介意,您是否介意尝试帮我看看我是否可以通过我当前的实现绑定到 ObservableCollection?下面是我的xaml和解释。
<Window.Resources>
<local:flex2kSQLDataSet x:Key="Flex2kSQLDataSet" />
<CollectionViewSource x:Key="cvOrderStatuses" Source="{Binding spGetProductionDashboardStatuses, Source={StaticResource Flex2kSQLDataSet}}" />
<CollectionViewSource x:Key="VwProductionScheduleWPFMainViewSource" Source="{Binding vwProductionScheduleWPFMain, Source={StaticResource Flex2kSQLDataSet}}" />
<Grid DataContext="{StaticResource VwProductionScheduleWPFMainViewSource}">
VwProductionScheduleWPFMainViewSource 使用 SQL 服务器视图和 table 适配器。是否可以使用此视图并创建一个 ObservableCollection 并将其绑定到数据网格?如果是这样,如果您能提供代码建议或为我指明正确的方向,我将不胜感激!
更新 #3:
康斯坦丁,我想我已经接近了,但需要更多帮助。
模块级别:
作为对象的私有项目
Private Property Items() As ObservableCollection(Of vwProductionScheduleWPFMain)
Get
Return m_Items
End Get
Set(value As ObservableCollection(Of vwProductionScheduleWPFMain))
m_Items = value
End Set
End Property
Private m_Items As ObservableCollection(Of vwProductionScheduleWPFMain)
表单加载:
Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs) 句柄 MyBase.Loaded
尝试
dataGrid1.DataContext = Me
绑定数据程序:
私有子 BindData()
尝试
Dim db As TFCDataContext
db = New TFCDataContext
Items = New ObservableCollection(Of vwProductionScheduleWPFMain)(db.vwProductionScheduleWPFMains)
dataGrid1.ItemsSource = Items
查找程序:
Private Sub OnSelectionButtonClick(发件人作为对象,e 作为 RoutedEventArgs)
尝试
Dim so As Integer = Convert.ToInt32(Me.txtFind.Text)
Item = Items.Where(Function(x) x.SalesOrder = so)
dataGrid1.SelectedItem = Item
Catch ex As Exception
MessageBox.Show(ex.Message, "Find button click error", MessageBoxButton.OK, MessageBoxImage.Error)
End Try
End Sub
XAML 对于网格:
我可以看到我的 Items 可观察集合正在获取正确的数据,并且 find 方法成功找到了记录。但是,找到的记录并不是select 网格中的记录。我缺少什么才能让它在网格中找到记录?
此外,我注意到如果我删除加载事件上的 DataContext 设置,数据仍会加载。是需要将 DataContext 设置为 (me/this) 还是我设置不正确?再次感谢您的帮助!
更新 #4:
我已经成功地在可观察的项目集合中找到了搜索的项目并将其分配给一个对象项目,但是当我设置数据网格的 SelectedItem 属性 时,该行不是 selected,这是我真正需要的。如果您能提供帮助或提供示例代码,我们将不胜感激。下面是我的代码,显示该项目已找到(但该行未 selected)。
XAML 对于设置了 ItemSource 和 SelectedItem 的数据网格:
<DataGrid x:Name="dataGrid1"
AutoGenerateColumns="False"
CanUserReorderColumns="True"
CanUserAddRows="False"
IsReadOnly="False"
CanUserResizeColumns="True"
EnableRowVirtualization="True"
ItemsSource="{Binding Items}"
SelectedItem="{Binding Item}"
CanUserSortColumns="True"
RowHeight="25"
Margin="10,15,10,10"
Grid.Row="3"
Sorting="DataGrid_Standard_Sorting">
尝试执行以下操作(我将在此处使用 c#,但 vb.net 几乎完全相同)
- 您的 DataGrid 定义应该是这样的:
<DataGrid ItemsSource="{Binding Items}" SelectedItem="{Binding Item}" .../>
- 当您搜索时,您只需这样做:
Item = Items.Where(p=> ...);
- 然后根据您的代码实现,您应该将 DataGrid 滚动到选定的行中
希望对您有所帮助
ObservableCollection 是最好的实现。下面的示例代码。
Public Property MyCollection() As ObservableCollection(Of YourClass)
Get
Return m_MyCollection
End Get
Set(value As ObservableCollection(Of YourClass))
m_MyCollection = value
End Set
End Property
Private m_MyCollection As New ObservableCollection(Of YourClass)
Dim findItem As YourClass
findItem = MyCollection.First(Function(x) x.SalesOrder = so)
dataGrid1.SelectedItem = findItem
dataGrid1.ScrollIntoView(findItem)
我在网上搜索过并亲自尝试过,但无法找到一种方法来准确地 select 记录编程,方法是在具有分组数据的数据网格上提供搜索值。下面的代码适用于未分组的数据,但是当数据被分组时,索引似乎不再有效并且分组似乎在数据的索引上。
这是表格的屏幕截图。数据已分组。用户输入销售订单号并单击查找按钮。我想记录为该行找到的要突出显示的内容。
这是找到记录时未分组的数据,可以看到高亮显示的记录:
下面是我的代码。单击“查找”按钮时会触发 OnSelectionButtonClick 事件。 cmdAddRemoveGroup_Click 过程中的数据是 grouped/ungrouped。数据在 RebindData 过程中绑定到网格。将销售订单传递到 SelectGridRow 过程以 select 一行(如果找到)。
感谢任何帮助! 谢谢,吉米
'Module level scope
Private da As wpfProductionDashboard.flexDataSetTableAdapters.vwProductionScheduleWPFMainTableAdapter = New wpfProductionDashboard.flexDataSetTableAdapters.vwProductionScheduleWPFMainTableAdapter()
Private Sub OnSelectionButtonClick(sender As Object, e As RoutedEventArgs)
Try
Dim so As Integer = Convert.ToInt32(Me.txtFind.Text)
Dim index As Integer = FlexDataSet.vwProductionScheduleWPFMain.Rows.IndexOf(FlexDataSet.vwProductionScheduleWPFMain.Rows.Find(so))
'Dim index2 As Integer = 1
'For Each c In FlexDataSet.vwProductionScheduleWPFMain.Rows
' If c(0) = so Then
' SelectGridRow(dataGrid1, index2)
' Exit Sub
' End If
' Console.WriteLine(c(0))
' index2 += 1
'Next
If index > 0 Then
Console.WriteLine(index.ToString())
SelectGridRow(dataGrid1, index)
End If
Catch ex As Exception
MessageBox.Show(ex.Message, "Find button click error", MessageBoxButton.OK, MessageBoxImage.Error)
End Try
End Sub
Private Sub SelectGridRow(ByVal DataGrid As DataGrid, ByVal rowIndex As Integer)
If Not DataGrid.SelectionUnit.Equals(DataGridSelectionUnit.FullRow) Then
Throw New ArgumentException("The SelectionUnit of the DataGrid must be set to FullRow.")
End If
If rowIndex < 0 OrElse rowIndex > (DataGrid.Items.Count - 1) Then
Throw New ArgumentException(String.Format("{0} is an invalid row index.", rowIndex))
End If
DataGrid.SelectedItems.Clear()
Dim item As Object = DataGrid.Items(rowIndex)
DataGrid.SelectedItem = item
Dim row As DataGridRow = TryCast(DataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex), DataGridRow)
If row Is Nothing Then
' bring the data item into view
DataGrid.ScrollIntoView(item)
row = TryCast(DataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex), DataGridRow)
End If
End Sub
Private Sub cmdAddRemoveGroup_Click(sender As Object, e As RoutedEventArgs) Handles cmdAddRemoveGroup.Click
Try
If cmdAddRemoveGroup.IsChecked = False Then
FlexDataSet.vwProductionScheduleWPFMain.DefaultView.RowFilter = "SalesOrderStatus <> 'Hold' and SalesOrderStatus <> 'Approval Done'"
vw.GroupDescriptions.Add(New PropertyGroupDescription("SalesOrderStatusGroup", New OpenStatusConverter))
Else
vw.GroupDescriptions.Clear()
End If
SortDataGrid()
Catch ex As Exception
MessageBox.Show(ex.Message, "Grouping Event", MessageBoxButton.OK, MessageBoxImage.Error)
End Try
End Sub
Private Sub RebindData()
Try
Dim taStatuses As wpfProductionDashboard.flexDataSetTableAdapters.spGetProductionDashboardStatusesTableAdapter = New wpfProductionDashboard.flexDataSetTableAdapters.spGetProductionDashboardStatusesTableAdapter()
da.Fill(FlexDataSet.vwProductionScheduleWPFMain)
taStatuses.Fill(FlexDataSet.spGetProductionDashboardStatuses)
vw.View.MoveCurrentToFirst()
cvOrderStatuses.View.MoveCurrentToFirst()
lstOrderStatus.ItemsSource = cvOrderStatuses.View
Catch ex As Exception
MessageBox.Show(ex.Message, "Rebind Data Event", MessageBoxButton.OK, MessageBoxImage.Error)
End Try
End Sub
谢谢康斯坦丁。我怕你会这么说。我还没有想出如何实现 ObservableCollection,因为这个应用程序不使用 MVVM。如果您不介意,而且我理解您是否介意或不想介意,您是否介意尝试帮我看看我是否可以通过我当前的实现绑定到 ObservableCollection?下面是我的xaml和解释。
<Window.Resources>
<local:flex2kSQLDataSet x:Key="Flex2kSQLDataSet" />
<CollectionViewSource x:Key="cvOrderStatuses" Source="{Binding spGetProductionDashboardStatuses, Source={StaticResource Flex2kSQLDataSet}}" />
<CollectionViewSource x:Key="VwProductionScheduleWPFMainViewSource" Source="{Binding vwProductionScheduleWPFMain, Source={StaticResource Flex2kSQLDataSet}}" />
<Grid DataContext="{StaticResource VwProductionScheduleWPFMainViewSource}">
VwProductionScheduleWPFMainViewSource 使用 SQL 服务器视图和 table 适配器。是否可以使用此视图并创建一个 ObservableCollection 并将其绑定到数据网格?如果是这样,如果您能提供代码建议或为我指明正确的方向,我将不胜感激!
更新 #3: 康斯坦丁,我想我已经接近了,但需要更多帮助。
模块级别: 作为对象的私有项目
Private Property Items() As ObservableCollection(Of vwProductionScheduleWPFMain)
Get
Return m_Items
End Get
Set(value As ObservableCollection(Of vwProductionScheduleWPFMain))
m_Items = value
End Set
End Property
Private m_Items As ObservableCollection(Of vwProductionScheduleWPFMain)
表单加载: Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs) 句柄 MyBase.Loaded 尝试
dataGrid1.DataContext = Me
绑定数据程序: 私有子 BindData() 尝试 Dim db As TFCDataContext
db = New TFCDataContext
Items = New ObservableCollection(Of vwProductionScheduleWPFMain)(db.vwProductionScheduleWPFMains)
dataGrid1.ItemsSource = Items
查找程序: Private Sub OnSelectionButtonClick(发件人作为对象,e 作为 RoutedEventArgs) 尝试 Dim so As Integer = Convert.ToInt32(Me.txtFind.Text)
Item = Items.Where(Function(x) x.SalesOrder = so)
dataGrid1.SelectedItem = Item
Catch ex As Exception
MessageBox.Show(ex.Message, "Find button click error", MessageBoxButton.OK, MessageBoxImage.Error)
End Try
End Sub
XAML 对于网格:
我可以看到我的 Items 可观察集合正在获取正确的数据,并且 find 方法成功找到了记录。但是,找到的记录并不是select 网格中的记录。我缺少什么才能让它在网格中找到记录?
此外,我注意到如果我删除加载事件上的 DataContext 设置,数据仍会加载。是需要将 DataContext 设置为 (me/this) 还是我设置不正确?再次感谢您的帮助!
更新 #4: 我已经成功地在可观察的项目集合中找到了搜索的项目并将其分配给一个对象项目,但是当我设置数据网格的 SelectedItem 属性 时,该行不是 selected,这是我真正需要的。如果您能提供帮助或提供示例代码,我们将不胜感激。下面是我的代码,显示该项目已找到(但该行未 selected)。
XAML 对于设置了 ItemSource 和 SelectedItem 的数据网格:
<DataGrid x:Name="dataGrid1"
AutoGenerateColumns="False"
CanUserReorderColumns="True"
CanUserAddRows="False"
IsReadOnly="False"
CanUserResizeColumns="True"
EnableRowVirtualization="True"
ItemsSource="{Binding Items}"
SelectedItem="{Binding Item}"
CanUserSortColumns="True"
RowHeight="25"
Margin="10,15,10,10"
Grid.Row="3"
Sorting="DataGrid_Standard_Sorting">
尝试执行以下操作(我将在此处使用 c#,但 vb.net 几乎完全相同)
- 您的 DataGrid 定义应该是这样的:
<DataGrid ItemsSource="{Binding Items}" SelectedItem="{Binding Item}" .../>
- 当您搜索时,您只需这样做:
Item = Items.Where(p=> ...);
- 然后根据您的代码实现,您应该将 DataGrid 滚动到选定的行中
希望对您有所帮助
ObservableCollection 是最好的实现。下面的示例代码。
Public Property MyCollection() As ObservableCollection(Of YourClass)
Get
Return m_MyCollection
End Get
Set(value As ObservableCollection(Of YourClass))
m_MyCollection = value
End Set
End Property
Private m_MyCollection As New ObservableCollection(Of YourClass)
Dim findItem As YourClass
findItem = MyCollection.First(Function(x) x.SalesOrder = so)
dataGrid1.SelectedItem = findItem
dataGrid1.ScrollIntoView(findItem)