【发布时间】:2018-05-09 02:40:41
【问题描述】:
我正在使用 WPF 客户端应用程序,它使用列表框来显示行程。我的任务是实现拖放功能以重新排序工作列表中的列表项,从而重新排序行程。工作列表中的每个项目都有自己的视图和视图模型,橙色箭头(开始许可证检查),红色许可证编号(显示有关许可证的更多信息)和复选框(选择项目以便检查上传检查或保存更改。还会触发列表框视图上的按钮变为活动状态)都位于该视图中。
我已经使用列表框后面的代码和 PreviewLeftMouseButtonDown 触发器完成了拖放操作。但是,上述触发器似乎消耗了复选框的触发器,而不是红色按钮或橙色按钮。但是,列表框视图上的“全选”按钮仍然有效。
这是列表项的 XAML 代码,压缩后仅显示复选框代码:
<StackPanel Grid.Row="0" Grid.Column="0" Grid.RowSpan="3">
<CheckBox ClickMode="Press" IsTabStop="False" Style="{DynamicResource CheckBoxStyle}" HorizontalAlignment="Left" VerticalAlignment="Top" IsChecked="{Binding IsSelected,Mode=TwoWay,FallbackValue='False'}" Margin="0 2 0 0"></CheckBox>
<Border BorderBrush="{DynamicResource GrayBorder}" BorderThickness="0 0 1 0"/>
</StackPanel>
这是红色许可证号框的代码,仍然可以进行比较:
<StackPanel Grid.Row="0" Grid.Column="1" Margin="4 4 4 4">
<StackPanel Orientation="Horizontal">
<Button IsTabStop="False" ClickMode="Press" Command="{Binding PermitDetailViewCommand}" CommandParameter="{Binding RequestInfo.PermitNumber}" Style="{StaticResource PermitDetailButton}" Content="{Binding RequestInfo.PermitNumber, Mode=OneTime,FallbackValue=''}"/>
<Button Style="{StaticResource CriticalIconStyle}" Visibility="{Binding RequestInfo.IsCritical, Converter={StaticResource BooleanToVisibility}}" Margin="0,4,0,0" ToolTip="{Binding RequestInfo.CriticalInformation}" Height="14" IsTabStop="False"/>
<Button Style="{StaticResource ContactIconStyle}" Content="{Binding RequestInfo.ContactAttemptedCountCode}" Visibility="{Binding RequestInfo.ContactAttemptedCountCode, Converter={StaticResource StringToVisibility}}" Margin="0,2,0,0" IsTabStop="False"/>
</StackPanel>
</StackPanel>
下面是实例化列表框中每个项目的 XAML 代码:
<ListBox Margin="4,8" ItemsSource="{Binding Path=CheckedOutVM,Mode=TwoWay,IsAsync=True}"
SelectedItem="{Binding Path=SelectedLocalPermit}" Grid.Row="1" Grid.Column="0" BorderThickness="0"
KeyboardNavigation.TabNavigation="Continue" Name="RequestCheckedOutV" BorderBrush="{DynamicResource DarkBorder}" attprop:ArrowKeyPressed.IsEnabled="True">
<i:Interaction.Triggers>
<i:EventTrigger EventName="ClickMode.Press">
<cmd:EventToCommand
Command="{Binding SelectedLocalCommand}"
CommandParameter="{Binding SelectedItem}"
/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Control.HorizontalContentAlignment" Value="Center"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
<Setter Property="Control.VerticalContentAlignment" Value="Top"/>
<Setter Property="AllowDrop" Value="True"/>
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="S_PreviewMouseLeftButtonDown"/>
<EventSetter Event="Drop" Handler="listbox1_Drop"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}" >
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate >
<ContentControl Content="{Binding}" IsTabStop="False"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
这是列表框后面允许拖放的代码:
public partial class WorklistSmallView : UserControl
{
WorklistSmallViewModel vm = new WorklistSmallViewModel();
/// <summary>
/// Initializes a new instance of the WorklistSmallView class.
/// </summary>
public WorklistSmallView()
{
InitializeComponent();
}
private void S_PreviewMouseLeftButtonDown(object sender, MouseEventArgs e)
{
WorklistSmallViewModel vm = new WorklistSmallViewModel();
ListBoxItem draggedItem = sender as ListBoxItem;
draggedItem.IsSelected = true;
DragDrop.DoDragDrop(draggedItem, draggedItem.DataContext, DragDropEffects.Move);
vm = RequestCheckedOutV.DataContext as WorklistSmallViewModel;
}
}
void listbox1_Drop(object sender, DragEventArgs e)
{
WorklistSmallDetailViewModel droppedData = e.Data.GetData(typeof(WorklistSmallDetailViewModel)) as WorklistSmallDetailViewModel;
WorklistSmallDetailViewModel target = ((ListBoxItem)(sender)).DataContext as WorklistSmallDetailViewModel;
int removedIdx = RequestCheckedOutV.Items.IndexOf(droppedData);
int targetIdx = RequestCheckedOutV.Items.IndexOf(target);
if (removedIdx < targetIdx)
{
vm = (WorklistSmallViewModel)RequestCheckedOutV.DataContext;
vm.CheckedOutVM.Insert(targetIdx + 1, droppedData);
vm.CheckedOutVM.RemoveAt(removedIdx);
}
else
{
int remIdx = removedIdx + 1;
if (vm.CheckedOutVM.Count + 1 > remIdx)
{
vm.CheckedOutVM.Insert(targetIdx, droppedData);
vm.CheckedOutVM.RemoveAt(remIdx);
}
}
foreach (var item in vm.CheckedOutVM)
{
item.RouteOrder = RequestCheckedOutV.Items.IndexOf(item) + 1;
}
RequestCheckedOutV.Items.Refresh();
}
}
感谢您提供的任何帮助,如果您需要更多信息,请告诉我。
Update#1 故障排除尝试和结果 1、去掉checkbox的动态样式,使用checkbox。结果 - 复选框没有变化。似乎该事件没有进入 ListBox 项,但它仍然允许单击按钮。
- 在列表框中将事件更改为 MouseLeftButtonDown 事件。结果复选框有效,拖放功能无效。似乎 PreviewMouseEvent 与普通 MouseEvent 的时间安排是允许拖放工作的原因。
【问题讨论】:
-
如果您从复选框中删除定义的样式,您会得到相同的结果吗?
-
是的,先生。那是我尝试的第一件事。有趣的是红色按钮仍在工作,这是否意味着 listBox 没有消耗该事件?
-
嗯,你的红色和橙色按钮是
Button类型的吗?这可以解释一些事情,因为您的 ListBoxItem 继承自Checkbox派生的同一个ToggleButton类。我的意思是有一些简单的解决方法,但让我想一想,自从大约一年前翻到 Web 内容后,我在 wpf/xaml 方面有点生疏,但我们肯定可以解决。 -
解决方法也可以,我只需要它让我选中复选框并拖动项目以在列表中重新定位。