【发布时间】:2011-11-01 15:47:26
【问题描述】:
这会让我发疯。我有一个 WPF ListView,我尝试在双击的单元格上覆盖一个 TextBox 以模拟一个编辑器。到目前为止,这工作正常。我调用 ListView.InputHitTest(e.Position) 来获取点击的项目。从那里我使用 VisualTreeHelper.GetParent() 在 VisualTree 中导航并解析坐标。很好。
现在我想要,如果用户按下光标,这个 TextBox 会移动到下一个项目。我尝试了以下尝试:
ListView.ItemContainerGenerator.ContainerFromIndex(index + 1)
ListView.ItemContainerGenerator.ContainerFromItem(…)
但是这两种方法都返回 null(在 VB 中为空),但 ListView.ItemContainerGenerator.Status 返回 ContainersGenerated。 如何获取特定 ListViewItem 的坐标?
顺便说一句:我仅限于 Framework 3.5,因此 4.0 中的 Grid 不可用。此外,我不想使用 3rd 方工具。
编辑
这是我使用的一些(实验性)代码:
我使用周围的 Canvas 轻松地将 TextBox 放置在 ListView 上。我包括了第一列的 DataTemplate。其余部分非常相似,因此我删除了此代码。此外,我删除了一些样式定义和转换器 - 我认为它们在这里没有任何意义。
<Canvas x:Name="Canvas">
<ListView ItemsSource="{Binding MyListViewList}"
Name="ListView"
MouseDoubleClick="ListView_MouseDoubleClick">
<ListView.Resources>
<DataTemplate x:Key="NameTemplate">
<Border Name="NameBorder">
<!-- Some content for this cell here -->
</Border>
</DataTemplate>
</ListView.Resources>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
<Setter Property="VerticalContentAlignment" Value="Stretch"></Setter>
<Setter Property="IsSelected" Value="{Binding IsSelected}"></Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Name" x:Name="colName"
CellTemplate="{StaticResource NameTemplate}"></GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
<TextBox Name="EditorTextBox"
Visibility="Hidden"
BorderThickness="0">
</TextBox>
</Canvas>
我注册 PreviewKeyDown 以捕捉 Cursor-Down 上的按键:
Private Sub TextBox_PreviewKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
Dim model As MyListViewModel
model = CType(DataContext, MyListViewModel)
Select Case e.Key
Case Key.Down
Dim lvp As MyListViewParameter
If Me.editorSelectedItemIndex + 1 < model.MyListViewList.Count Then
lvp = model.MyListViewList(Me.editorSelectedItemIndex + 1)
' How to position EditorTextBox to the next ListViewItem here?
' The following methods return null/Nothing:
' ListView.ItemContainerGenerator.ContainerFromIndex(editorSelectedItemIndex + 1)
' ListView.ItemContainerGenerator.ContainerFromItem(lvp)
End If
e.Handled = True
Case Key.Up
End Select
End Sub
所以当我需要重新排列 TextBox 时,我在代码中的位置(PreviewKeyDown-Event),但是在这个例程中,我无法获得方法的结果
ListView.ItemContainerGenerator.ContainerFromIndex(index + 1) 和
ListView.ItemContainerGenerator.ContainerFromItem(…)
进一步测试:
我写了一个类,它继承 ListView 并在 ListViewItem 的简单列表中创建时缓存 ListViewItems
Public Class ExtListView
Inherits ListView
Public Sub New()
Dim ic = TryCast(Me.Items, System.Collections.Specialized.INotifyCollectionChanged)
If Not ic Is Nothing Then
AddHandler ic.CollectionChanged, AddressOf NotifyCollectionChangedEventHandler
End If
AddHandler Me.ItemContainerGenerator.StatusChanged, AddressOf ItemContainerGenerator_ItemsChanged
_ListViewItems = New List(Of ListViewItem)
End Sub
Private _listViewItems As List(Of ListViewItem)
Public ReadOnly Property ListViewItems As List(Of ListViewItem)
Get
Return _listViewItems
End Get
End Property
Private Sub ItemContainerGenerator_ItemsChanged(ByVal sender As Object, ByVal e As EventArgs)
If Me.ItemContainerGenerator.Status = Primitives.GeneratorStatus.ContainersGenerated Then
_listViewItems.Clear()
For index = 0 To Me.Items.Count - 1
_listViewItems.Add(CType(ItemContainerGenerator.ContainerFromIndex(index), ListViewItem))
Next
End If
End Sub
End Class
有了这个 ListViewItems 可用,我试图获得它们的界限:
Dim bounds As Rect = VisualTreeHelper.GetDescendantBounds(ListView.ListViewItems(editorSelectedItemIndex + 1))
但是,所有矩形都从 x,y 位置 (0, 0) 开始。我不知道为什么。我希望它们位于可视树中的有效位置。 有什么解决这个问题的建议吗?
【问题讨论】:
-
什么是 ItemsSource? ItemTemplate 怎么样?你能发布一些代码(除非它太长)?
-
@MarioVernari:我希望这是一个可管理的来源。我试图发布重要的行。
标签: wpf listview gridview .net-3.5 listviewitem