WPF ListBox SelectedItems определяет нажатие Ctrl или Shift для выбора

Мне нужно знать, заполнялись ли SelectedItems при нажатии Ctrl или Shift или нет. Есть ли простой способ (без создания нового шаблона управления) получить эту информацию? Я предпочитаю решения без кода.

С уважением Янник


person Yannik    schedule 28.04.2015    source источник
comment
Зачем вам эта информация? Просто установите для SelectionMode значение MultiExtended, и ваши SelectedItems будут заполнены.   -  person Michi-2142    schedule 28.04.2015
comment
Мне нужно собрать выбранные элементы из различных дочерних моделей представления, а в основной модели представления я хочу действовать при выборе всех дочерних моделей представления. Если выбран только один элемент (по всем дочерним моделям представления), я действую иначе, чем при выборе нескольких элементов. Выборки в дочерних моделях представления привязаны к пользовательской коллекции ObservableCollection, которая привязана к SelectedItems из ListBox.   -  person Yannik    schedule 28.04.2015


Ответы (2)


Вы можете подключить событие изменения выбора и проверить, нажаты ли клавиши-модификаторы для выбора.

    void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var isCtrlorShiftDown = (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl) || Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift));
        if (isCtrlorShiftDown)
        {
            // Write your Logic Here;
        }
    }
person Arun Selva Kumar    schedule 28.04.2015
comment
Спасибо, но это именно тот код, который я не хочу использовать :-) - person Yannik; 30.04.2015

Я нашел решение с минимальным кодом.

Основная концепция заключается в том, что я присоединяюсь к событиям KeyDown и KeyUp в MainWindow и устанавливаю свойство «CurrentKeyboardKeyPressed» в MainViewModel, которое распространяет информацию о нажатой клавише на дочерние модели представления, которые, в свою очередь, запускают пользовательское событие со специальным выбором. класс, который имеет текущую информацию о нажатой клавише.

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

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    private readonly MainWindowViewModel _mainWindowViewModel;

    public MainWindow()
    {
        _mainWindowViewModel = new MainWindowViewModel();
        InitializeComponent();

        DataContext = _mainWindowViewModel;
    }

    private void MainWindow_OnKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
        {
            _mainWindowViewModel.CurrentKeyboardKeyPressed = PressedKeyboardKey.Ctrl;
            return;
        }

        if (e.Key == Key.LeftShift || e.Key == Key.RightShift)
        {
            _mainWindowViewModel.CurrentKeyboardKeyPressed = PressedKeyboardKey.Shift;
        }
    }

    private void MainWindow_OnKeyUp(object sender, KeyEventArgs e)
    {
        _mainWindowViewModel.CurrentKeyboardKeyPressed = PressedKeyboardKey.None;
    }
}

MainWindowViewModel.cs

public class MainWindowViewModel : ViewModelBase
{
    // child view models
    private readonly ObservableCollection<TTSViewModel> _ttsViewModels;

    private PressedKeyboardKey _currentKeyboardKeyPressed;

    public EventHandler<KeyboardKeyPressedEventArgs> CurrentKeyboardKeyPressedChanged;

    public MainWindowViewModel()
    {
        _ttsViewModels = new ObservableCollection<TTSViewModel>();
    }

    public PressedKeyboardKey CurrentKeyboardKeyPressed
    {
        get { return _currentKeyboardKeyPressed; }
        set
        {
            if (_currentKeyboardKeyPressed != value)
            {
                _currentKeyboardKeyPressed = value;
                OnCurrentKeyboardKeyPressedChanged(_currentKeyboardKeyPressed);
            }
        }
    }

    // create child view models
    public void PopulateTTSList(int itemsToCreated)
    {
        for (int i = 0; i < itemsToCreated; i++)
        {
            var tts = new TTSViewModel("TTS " + i);

            tts.FractionSelectionChanged += OnTTSFractionSelectionChanged;
            CurrentKeyboardKeyPressedChanged += tts.CurrentKeyboardKeyPressedChanged;
            _ttsViewModels.Add(tts);
        }
    }

    private void OnCurrentKeyboardKeyPressedChanged(PressedKeyboardKey currentKeyboardKeyPressed)
    {
        var handler = CurrentKeyboardKeyPressedChanged;
        if (handler != null)
        {
            handler(this, new KeyboardKeyPressedEventArgs(currentKeyboardKeyPressed));
        }
    }

    // selection changed handler for each child view model
    private void OnTTSFractionSelectionChanged(object sender, ItemSelectionChangedEventArgs fractionSelectionChangedEventArgs)
    {
        var sendingTTS = sender as TTSViewModel;
        if (fractionSelectionChangedEventArgs.Selection.PressedKeyOnSelection == PressedKeyboardKey.None)
        {
            // single selection action goes here
            // ....
        }
        else
        {
            // multi selection action goes here
            // ....
        }
    }
}

TTSViewModel.cs (модель дочернего представления)

public class TTSViewModel : ViewModelBase
{
    private readonly SmartObservableCollection<FractionViewModel> _currentlySelectedfractions;
    public EventHandler<ItemSelectionChangedEventArgs> FractionSelectionChanged;
    private PressedKeyboardKey _currentKeyboardKeyPressed;

    public TTSViewModel()
    {
        _currentlySelectedfractions = new SmartObservableCollection<FractionViewModel>();
        _currentlySelectedfractions.CollectionChanged += CurrentlySelectedfractionsOnCollectionChanged;
    }

    public void CurrentKeyboardKeyPressedChanged(object sender, KeyboardKeyPressedEventArgs currentKeyboardKeyPressedEventArgs)
    {
        _currentKeyboardKeyPressed = currentKeyboardKeyPressedEventArgs.CurrentKeyboardKeyPressed;
    }

    private void CurrentlySelectedfractionsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
    {
        if (FractionSelectionChanged != null)
        {
            if (notifyCollectionChangedEventArgs.Action == NotifyCollectionChangedAction.Replace && notifyCollectionChangedEventArgs.NewItems != null)
            {
                var removed = _oldSelectedfractions.Except(_currentlySelectedfractions);
                var added = _currentlySelectedfractions.Except(_oldSelectedfractions);

                var selection = new Selection<FractionViewModel>(added, removed, _currentKeyboardKeyPressed);

                _oldSelectedfractions.Clear();
                foreach (var currentlySelectedfraction in _currentlySelectedfractions)
                {
                    _oldSelectedfractions.Add(currentlySelectedfraction);
                }

                var selectionChangedArgs = new ItemSelectionChangedEventArgs(selection);
                FractionSelectionChanged(this, selectionChangedArgs);
            }
        }
    }
}

Selection.cs

public sealed class Selection<T>
{
    private readonly List<T> _added;
    private readonly List<T> _removed;
    private readonly PressedKeyboardKey _currentKeyboardKeyPressed;

    public Selection()
    {
        _added = new List<T>();
        _removed = new List<T>();
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="Selection{T}" /> class.
    /// </summary>
    /// <param name="addedItems">[NotNull]</param>
    /// <param name="removedItems">[NotNull]</param>
    /// <param name="currentKeyboardKeyPressed">The current keyboard key pressed.</param>
    public Selection(IEnumerable<T> addedItems, IEnumerable<T> removedItems, PressedKeyboardKey currentKeyboardKeyPressed)
    : this()
    {
        _added.AddRange(addedItems);
        _removed.AddRange(removedItems);
        _currentKeyboardKeyPressed = currentKeyboardKeyPressed;
    }

    public IReadOnlyList<T> Added
    {
        get { return _added; }
    }

    public IReadOnlyList<T> Removed
    {
        get { return _removed; }
    }

    public PressedKeyboardKey PressedKeyOnSelection
    {
        get { return _currentKeyboardKeyPressed; }
    }
}

KeyboardKeyPressedEventArgs.cs

public sealed class KeyboardKeyPressedEventArgs : EventArgs
{
    public KeyboardKeyPressedEventArgs(PressedKeyboardKey currentKeyboardKeyPressed)
    {
        CurrentKeyboardKeyPressed = currentKeyboardKeyPressed;
    }

    public PressedKeyboardKey CurrentKeyboardKeyPressed { get; private set;     }
}

ItemSelectionChangedEventArgs.cs

public sealed class ItemSelectionChangedEventArgs : EventArgs
{
    public ItemSelectionChangedEventArgs(Selection<FractionViewModel> newSelection)
    {
        Selection = newSelection;
    }

    public Selection<FractionViewModel> Selection { get; private set; }
}

PressedKeyboardKey.cs

public enum PressedKeyboardKey
{
    None,
    Ctrl,
    Shift
}
person Yannik    schedule 28.04.2015