Флажок триггера WPF для элемента списка из ListBox с функцией перетаскивания - PullRequest
0 голосов
/ 07 мая 2018

Я работаю с клиентским приложением 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. изменил событие на MouseLeftButtonDown в listBox. Флажок результата работает, функция перетаскивания - нет. похоже, что время PreviewMouseEvent по сравнению с обычным MouseEvent позволяет работать методом перетаскивания.

1 Ответ

0 голосов
/ 08 мая 2018

Итак, после тщательного поиска я попытался реализовать некоторую логику, когда события происходят, чтобы исключить потребление события. Я подумал, что если бы я вставил в событие утверждение «if» без else.

Я также обнаружил, что для этого мне нужны два триггера событий. Итак, вот триггеры событий, которые я использовал в представлении:

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

Мой обработчик выпадения вообще не изменился. Я не знаю, если это лучший способ сделать это, но это сработало для меня. Я полагаю, если это сэкономит мне время, надеюсь, это поможет и другим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...