从列表框中的列表项触发WPF复选框,其中包含拖放

时间:2018-05-07 16:51:38

标签: c# wpf xaml triggers

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

我使用列表框后面的代码和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();
    }
}

感谢您提供的任何帮助,如果您需要更多信息,请告诉我们。

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

  1. 将事件更改为listBox中的MouseLeftButtonDown事件。结果复选框有效,拖放功能没有。看起来像PreviewMouseEvent与普通MouseEvent的时间是允许拖放工作的时间。

1 个答案:

答案 0 :(得分:0)

因此,在详尽地搜索之后,我试图在事件发生时实现一些逻辑以消除事件的消耗。我想如果我要放一个&#39; if&#39;没有别的事件中的陈述。

我还发现我需要两个事件触发器才能执行此操作。以下是我在视图中使用的事件触发器:

 <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>

然后,在后面的代码中,我执行了拖放的所有逻辑,以便在不消耗事件的情况下移动项目: 首先,我需要创建2个局部变量,以便在整个代码中使用。 _startPoint是一个x,y点位置,用于比较移动。 dragAction是一个布尔值,它允许事件处理程序知道用户何时开始拖动操作。      public Point _startPoint {get;组; }         public bool dragAction = false;

在PreviewMouseButtonDown事件中,我将鼠标光标的起始位置设置为_startPoint。

    private void RequestCheckedOutV_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _startPoint = e.GetPosition(null);
    }

PreviewMouseMove处理程序是我将起点的位置与鼠标的释放位置进行比较的地方,然后将结果与系统参数中预设的最小移动规格进行比较。(我的预设为4)如果它更多那么最小值,处理程序知道它是一个Drag drop事件并调用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;
    }

我的掉落处理程序根本没有变化。 我不知道这是否是实现这一目标的最佳方式,但它对我有用。我想如果它为我节省了一些时间,希望它也会帮助其他人。