我开发了一个自定义项CheckedListBox
,用户可以使用它来指定哪些字段应该显示在报告中或不显示在报告中。我现在有一个来自用户的新要求,即能够按照他们希望在报告中看到的顺序对字段进行重新排序。我尝试这样做的方式是在我的CheckedListBox
.
目前,我正在使用该ListBoxItem.PreviewMouseMoveEvent
事件来启动拖动。结合PreviewMouseLeftButtonDownEvent
并PreviewMouseLeftButtonUpEvent
确定鼠标在移动过程中是否向下,并DropEvent
处理下降,一切正常。
但是,它似乎阻止了某些事件的触发,因为它破坏了与IsChecked
属性的绑定。事实上,我无法再选中/取消选中某个项目。绑定在 中完成ListBox.ItemTemplate
,其中有一个简单CheckBox
的包含TextBlock
用于显示文本的 a。
我尝试使用MouseMoveEvent
,它可以CheckBox
恢复生机,但会破坏拖放功能。似乎MouseMoveEvent
甚至不再触发(或者鼠标按钮事件之一不再触发)。
问题似乎出在这一行:DragDrop.DoDragDrop(draggedItem, draggedItem.DataContext, DragDropEffects.Move)
. 如果我删除它,我没有功能拖放,但所有事件都会正确触发。
这是我在实验阶段的代码示例:
Public Sub New()
' This call is required by the designer.
InitializeComponent()
Items = New ObservableCollection(Of CheckListBoxItem)
oListBox.ItemsSource = Items
' Add any initialization after the InitializeComponent() call.
oListBox.ItemContainerStyle.Setters.Add(New Setter(ListBoxItem.AllowDropProperty, True))
oListBox.ItemContainerStyle.Setters.Add(New EventSetter(ListBoxItem.PreviewMouseLeftButtonDownEvent, New MouseButtonEventHandler(AddressOf ListBoxItem_PreviewMouseLeftButtonDown)))
oListBox.ItemContainerStyle.Setters.Add(New EventSetter(ListBoxItem.PreviewMouseLeftButtonUpEvent, New MouseButtonEventHandler(AddressOf ListBoxItem_PreviewMouseLeftButtonUp)))
oListBox.ItemContainerStyle.Setters.Add(New EventSetter(ListBoxItem.PreviewMouseMoveEvent, New MouseEventHandler(AddressOf ListBoxItem_PreviewMouseMove)))
oListBox.ItemContainerStyle.Setters.Add(New EventSetter(ListBoxItem.DropEvent, New DragEventHandler(AddressOf ListBoxItem_Drop)))
End Sub
Private source As CheckListBoxItem
Private bMouseLeftButtonDown As Boolean = False
Private Sub ListBoxItem_PreviewMouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs)
bMouseLeftButtonDown = True
End Sub
Private Sub ListBoxItem_PreviewMouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs)
bMouseLeftButtonDown = False
End Sub
Private Sub ListBoxItem_PreviewMouseMove(sender As Object, e As MouseEventArgs)
If TypeOf sender Is ListBoxItem AndAlso bMouseLeftButtonDown Then
Dim draggedItem As ListBoxItem = CType(sender, ListBoxItem)
source = CType(draggedItem.DataContext, CheckListBoxItem)
DragDrop.DoDragDrop(draggedItem, draggedItem.DataContext, DragDropEffects.Move)
draggedItem.IsSelected = True
End If
End Sub
Private Sub ListBoxItem_Drop(sender As Object, e As DragEventArgs)
bMouseLeftButtonDown = False
Dim target As CheckListBoxItem = CType((CType(sender, ListBoxItem)).DataContext, CheckListBoxItem)
Dim removedIdx As Integer = Items.IndexOf(source)
Dim targetIdx As Integer = Items.IndexOf(target)
If (removedIdx < targetIdx) Then
Items.Insert(targetIdx + 1, source)
Items.RemoveAt(removedIdx)
Else
Dim remIdx As Integer = removedIdx + 1
If (Items.Count + 1 > remIdx) Then
Items.Insert(targetIdx, source)
Items.RemoveAt(remIdx)
End If
End If
End Sub
这是我的 XAML 示例:
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked}">
<TextBlock Text="{Binding DisplayText}" />
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
我正在寻找的是找到一个事件或一种处理事件的方法,这些事件将允许我进行功能性拖放以及功能性CheckBox
. 我会接受一个解释完全不同方法的答案,是否使用(免费)第三方库。
我不是在寻找依赖于特定 ViewModel 的代码,因为这旨在成为我们公司的可重用控件,并且并非所有内容都将按照 MVVM 样式完成。这就是我为每个列表项创建一个CheckListBoxItem
充当“DataContext”的具体原因。