C# 在具有拖放功能的ListBox中的列表项上触发WPF复选框

C# 在具有拖放功能的ListBox中的列表项上触发WPF复选框,c#,wpf,xaml,triggers,C#,Wpf,Xaml,Triggers,我正在使用一个WPF客户端应用程序,它使用一个列表框来显示行程。我的任务是实现拖放功能,以对工作列表中的列表项进行重新排序,从而对行程进行重新排序。工作列表中的每个项目都有自己的视图和视图模型,橙色箭头(启动许可证检查)、红色许可证编号(显示许可证的更多信息)和复选框(选择项目以上载检查或保存更改。还触发列表框视图上的按钮变为活动状态)都位于该视图中。 我已经使用listbox上的代码和PreviewLeftMouseButtonDown触发器完成了拖放。但是,前面提到的触发器似乎使用了复选框

我正在使用一个WPF客户端应用程序,它使用一个列表框来显示行程。我的任务是实现拖放功能,以对工作列表中的列表项进行重新排序,从而对行程进行重新排序。工作列表中的每个项目都有自己的视图和视图模型,橙色箭头(启动许可证检查)、红色许可证编号(显示许可证的更多信息)和复选框(选择项目以上载检查或保存更改。还触发列表框视图上的按钮变为活动状态)都位于该视图中。

我已经使用listbox上的代码和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();
    }
}
公共部分类WorklistSmallView:UserControl
{
WorklistSmallViewModel vm=新WorklistSmallViewModel();
/// 
///初始化WorklistSmallView类的新实例。
/// 
公共工作列表SmallView()
{
初始化组件();
}
private void S_PreviewMouseLeftButtonDown(对象发送器,MouseEventArgs e)
{
WorklistSmallViewModel vm=新WorklistSmallViewModel();
ListBoxItem draggedItem=作为ListBoxItem的发件人;
draggedItem.IsSelected=true;
DragDrop.DoDragDrop(draggedItem、draggedItem.DataContext、DragDropEffects.Move);
vm=RequestCheckedOutV.DataContext作为WorklistSmallViewModel;
}
}
无效列表框1_Drop(对象发送器,DragEventArgs e)
{
WorklistSmallDetailViewModel droppedData=e.Data.GetData(typeof(WorklistSmallDetailViewModel))作为WorklistSmallDetailViewModel;
WorklistSmallDetailViewModel目标=((ListBoxItem)(发件人)).DataContext作为WorklistSmallDetailViewModel;
int removedIdx=RequestCheckedOutV.Items.IndexOf(droppedData);
int-targetIdx=RequestCheckedOutV.Items.IndexOf(目标);
if(移除IDXremIdx)
{
vm.CheckedOutVM.Insert(targetIdx,droppedData);
vm.CheckedOutVM.RemoveAt(remIdx);
}
}
foreach(vm.CheckedOutVM中的变量项)
{
item.RouteOrder=RequestCheckedOutV.Items.IndexOf(item)+1;
}
RequestCheckedOutV.Items.Refresh();
}
}
我感谢任何提供的帮助,如果你需要任何更多的信息,请让我知道

更新#1故障排除尝试和结果 1.从复选框中删除动态样式并使用复选框。结果-复选框中没有更改。似乎事件没有进入ListBox项目,只是它仍然允许单击按钮

  • 在列表框中将事件更改为MouseLeftButtonDown事件。结果复选框起作用,但拖放功能不起作用。似乎PreviewMouseEvent与普通MouseEvent的计时是允许拖放工作的原因
    因此,在彻底搜索之后,我尝试在事件发生时实现一些逻辑,以消除事件的消耗。我想如果我在事件中使用“如果”语句,而不使用其他语句

    我还发现我需要两个事件触发器来完成这项工作。下面是我在视图中使用的事件触发器:

     <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="RequestCheckedOutV_PreviewMouseLeftButtonDown"/>
                    <EventSetter Event="PreviewMouseMove" Handler="RequestCheckedOutV_PreviewMouseMove"/>
                    <EventSetter Event="Drop" Handler="listbox1_Drop"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ListBoxItem}"  >
                                <ContentPresenter />
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
    
                </Style>
            </ListBox.ItemContainerStyle>
    
    PreviewMouseMove处理程序用于比较起点位置和鼠标释放位置,然后将结果与系统参数中预设的最小移动规格进行比较。(我的预设为4)如果超过最小值,处理程序知道这是一个拖放事件,并调用StartDrag并将dragAction设置为true

        private void RequestCheckedOutV_PreviewMouseMove(object sender, MouseEventArgs e)
        {
    
            if (Mouse.LeftButton == MouseButtonState.Pressed && !dragAction)
            {
                Point position = e.GetPosition(null);
                if (Math.Abs(position.X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance ||
    
                    Math.Abs(position.Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)
    
                {
                    dragAction = true;
                    this.StartDrag(sender, e);
                }
            }
        }
    
    下面的StartDrag方法实际上调用了DoDragDrop方法。然后,它还将拖动操作变量重置为false,以便在错误中删除它时,可以重置事件

        private void StartDrag(object sender, MouseEventArgs e)
        {
    
            ListBoxItem draggedItem = sender as ListBoxItem;
            draggedItem.IsSelected = true;
            DragDrop.DoDragDrop(draggedItem, draggedItem.DataContext, DragDropEffects.Move);
            dragAction = false;
        }
    
    我的投球手一点也没变。
    我不知道这是否是实现这一目标的最佳方式,但它对我来说很有效。我想如果它能为我节省一些时间,希望它也能帮助其他人

    如果你去掉复选框中定义的样式,你会得到同样的结果吗?是的,先生。这是我尝试的第一件事。有趣的是,红色按钮仍在工作,那么这是否意味着列表框没有使用事件?嗯,您的红色和橙色按钮是否为
    按钮
    ?这可以解释一些事情,因为ListBoxItem继承自
    ToggleButton
    类,而
    Checkbox
    派生自该类。我的意思是有一些简单的解决办法,但让我想想
        private void StartDrag(object sender, MouseEventArgs e)
        {
    
            ListBoxItem draggedItem = sender as ListBoxItem;
            draggedItem.IsSelected = true;
            DragDrop.DoDragDrop(draggedItem, draggedItem.DataContext, DragDropEffects.Move);
            dragAction = false;
        }