Как привязать двойной щелчок к элементу списка - PullRequest
0 голосов
/ 21 сентября 2018

У меня есть два списка, в которых хранятся коллекции.Текущая настройка такова, что когда элемент выбран в левом списке, вы можете нажать кнопку, чтобы добавить выбранное состояние в правый список.Для списков, которые связаны с пользовательской командой, есть кнопка добавления и удаления, причем выбранный элемент списка является параметром команды.

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

<ListBox x:Name="List" ItemContainerStyle="{StaticResource ListBoxItem}" DataContext="{StaticResource VM}" 
                            ItemsSource="{Binding Names, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" DisplayMemberPath="Name"
                                 Style="{StaticResource ResourceKey=ListBox}"/>


<Button Content="&gt;&gt;" Margin="5" Style="{StaticResource ResourceKey=MultiButton}" 
                            CommandParameter="{Binding ElementName=List}"
                            Command="{Binding Path=AddSelectedItemCommand}"/>

public void AddSelectedItem(object obj)
    {
        ListBox ListBox = obj as ListBox;
        List<Type> List = new List<Type>();
        if (Name == null)
            Name = new ObservableCollection<Type>();
        if (Name != null)
        {
            foreach (Type item in ListBox.SelectedItems.Cast<object>().ToList())
            {
                List.Add(item);
                Names.Remove(item);
            }

            foreach (Type listItem in List)
            {
                var state = Name.FirstOrDefault(aa => aa.Name == listItem.Name);
                if (state == null)
                {
                    Name.Add(listItem);
                }
            }
        }
        OnPropertyChanged("Name");
        OnPropertyChanged("Names");
    }

1 Ответ

0 голосов
/ 21 сентября 2018

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

Объекты должны знать только о своих вещах, от которых они зависята не те, которые от этого зависят.Поэтому ViewModel должен знать только о коллекциях данных, которые он делает доступными для любого клиента.

В вашем примере, что происходит, когда элемент управления изменяется из ListBox - вам придется изменить свою Команду.

Итак, во-первых, вам нужно изменить реализацию модели представления, в настоящее время у вас нет MVVM.

Вот полный список, который должен помочь вам на вашем пути:

<Window x:Class="WpfExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfExample"
        mc:Ignorable="d"
        Title="MainWindow" Height="140" Width="410">
   <Grid>
      <Grid.ColumnDefinitions>
         <ColumnDefinition />
         <ColumnDefinition />
      </Grid.ColumnDefinitions>
      <ListBox ItemsSource="{Binding Path=Names, Mode=OneWay}"
               SelectedItem="{Binding Path=SelectedName}">
         <ListBox.ItemTemplate>
            <DataTemplate>
               <TextBlock Text="{Binding .}">

                  <TextBlock.InputBindings>
                     <MouseBinding MouseAction="LeftDoubleClick" 
                                   Command="{Binding Path=DataContext.MyDoubleClickCommand, 
                                                     RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor} }" />
                  </TextBlock.InputBindings>
               </TextBlock>
            </DataTemplate>
         </ListBox.ItemTemplate>
      </ListBox>
      <ListBox Grid.Column="1" Margin="10,0,0,0" ItemsSource="{Binding Path=NamesTwo, Mode=OneWay}"
               SelectedItem="{Binding Path=SelectedNameTwo}">
         <ListBox.ItemTemplate>
            <DataTemplate>
               <TextBlock Text="{Binding .}">

                  <TextBlock.InputBindings>
                     <MouseBinding MouseAction="LeftDoubleClick" 
                                   Command="{Binding Path=DataContext.MyOtherDoubleClickCommand, 
                                                     RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor} }" />
                  </TextBlock.InputBindings>
               </TextBlock>
            </DataTemplate>
         </ListBox.ItemTemplate>
      </ListBox>
   </Grid>
</Window>

И код

namespace WpfExample
{
   /// <summary>
   /// Interaction logic for MainWindow.xaml
   /// </summary>
   public partial class MainWindow : Window
   {
      public MainWindow()
      {
         InitializeComponent();
         DataContext = new MyViewModel();
      }
   }
}

Затем существует ViewModel, который вы должны заметить, изменяет только те коллекции, которые открыты для представления для потребления

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using Prism.Commands;

namespace WpfExample
{
   public class MyViewModel : INotifyPropertyChanged
   {
      private string _selectedName;
      private string _selectedNameTwo;

      protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
      {
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      }

      public ObservableCollection<string> Names { get; } 
         = new ObservableCollection<string>(new List<string>
         {
            "Name1",
            "Name2",
            "Name3",
            "Name4",
            "Name5"
         });

      public ObservableCollection<string> NamesTwo { get; } = new ObservableCollection<string>(new List<string>());

      public string SelectedName
      {
         get { return _selectedName; }
         set { _selectedName = value; OnPropertyChanged(); }
      }

      public string SelectedNameTwo
      {
         get { return _selectedNameTwo; }
         set { _selectedNameTwo = value; OnPropertyChanged(); }
      }

      public ICommand MyOtherDoubleClickCommand
      {
         get
         {
            return new DelegateCommand<string>(name =>
            {
               NamesTwo.Remove(name);
               Names.Add(name);
               SelectedNameTwo = "";
            });
         }
      }

      public ICommand MyDoubleClickCommand
      {
         get
         {
            return new DelegateCommand<string>(name =>
            {
               Names.Remove(name);
               NamesTwo.Add(name);
               SelectedName = "";
            });
         }
      }

      public event PropertyChangedEventHandler PropertyChanged;
   }
}

Я использовал пакет Prism.Core для объекта DelegateCommand.Это не существенно, я просто сделал это для простоты

Вам даже не понадобятся свойства SelectedName и SelectedNameTwo, если они не будут использоваться при обработке ViewModel.Я включил их для полноты.

.

Отредактировано: Изначально я не заметил, что это для проекта UWP.Я полагаю, что следующее будет работать, хотя здесь это не проверено, поскольку в данный момент я не настроен на UWP на моей машине.Я не уверен в DoubleClick EventName .

<Page xmlns:i="using:Microsoft.Xaml.Interactivity"
      xmlns:core="using:Microsoft.Xaml.Interactions.Core>
  <ListBox Grid.Column="1" Margin="10,0,0,0" ItemsSource="{Binding Path=NamesTwo, Mode=OneWay}"
           SelectedItem="{Binding Path=SelectedNameTwo}">
     <ListBox.ItemTemplate>
        <DataTemplate>
           <TextBlock Text="{Binding .}" >
              <i:Interaction.Behaviors>
                 <core:EventTriggerBehavior EventName="DoubleClick">
                    <core:InvokeCommandAction Command="{Binding Path=DataContext.MyDoubleClickCommand, 
                                              RelativeSource={RelativeSource AncestorType=Page, Mode=FindAncestor} }" 
                                              CommandParameter="{Binding .}" />
                 </core:EventTriggerBehavior>
              </i:Interaction.Behaviors>
           </TextBlock>
        </DataTemplate>
     </ListBox.ItemTemplate>
  </ListBox>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...