Как запрограммировать событие «Изменение выбора» в ListBox в WPF? - PullRequest
2 голосов
/ 10 мая 2010

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

Я думал, что унаследую listbox и сделаю что-то, но внутренне все функции в классе Selector скрыты, что я вижу в отражателе, но я не могу унаследовать и переопределить любые методы !!

Ответы [ 6 ]

3 голосов
/ 21 июня 2010

Я вывел класс MyListBox из ListBox и добавил событие SelectionChanging, которое является отменяемым событием. Затем я использовал MyListBoxItem в качестве ItemContainer в MyListBox, который обрабатывает событие Preview Left Mouse Up и вызывает событие Selection Changing, при значении отмены я отмечаю событие как обработанное, что предотвращает новое выделение, а также позволяет уведомлять пользователя о необходимости чего-то.

1 голос
/ 10 мая 2010

Привязать IsSelected к свойству в классе модели представления и обработать регистр в установщике свойства, например ::

public bool IsSelected
{
   get { return _IsSelected; }
   set
   {
       if (value && DisableSelection)
       {
          AlertUser();
       }
       else
       {
          _IsSelected = value;
       }
       OnPropertyChanged("IsSelected");
   }
}

Обратите внимание, что вы вызываете событие PropertyChanged, даже если свойство не изменилось, потому что с точки зрения представления оно действительно изменилось.

0 голосов
/ 23 марта 2015

У меня была такая же потребность (спросите пользователя, действительно ли он хочет изменить выбранный элемент в единственном выборе ListBox), когда определенные критерии не выполнены. Важно иметь один выбор, иначе код становится более сложным. Я основал свое решение на ответе tempy, но обход визуального дерева казался слишком большой проблемой, поэтому я просто использовал listBox.ItemContainerGenerator, чтобы спросить элементы ListBox, находится ли мышь над какой-либо из них, и действовать соответственно:

    private void listBox_PreviewMouseDown(object sender, MouseButtonEventArgs e) {
        if (CheckIfCurrentlySelectedItemCanBeDeselected())
            // let things run normally
            return;

        var itemUnderMouse = GetListBoxItemUnderMouse(listBox);

        // check if there is no item under mouse
        // or if it is the currently selected item
        if (itemUnderMouse == null || itemUnderMouse.Content == currentItem)
            return;

        // always set Handled and take care of changing selection manually
        e.Handled = true;

        if (MessageBox.Show("The selected value is not valid, change selection?", "", MessageBoxButton.YesNo) == MessageBoxResult.Yes) {
            // change the value manually
            lbArticles.SelectedItem = itemUnderMouse.Content;
        }
    }

    private ListBoxItem GetListBoxItemUnderMouse(ListBox lb) {
        foreach (object o in lb.Items) {
            ListBoxItem lbi = lb.ItemContainerGenerator.ContainerFromItem(o) as ListBoxItem;

            if (lbi != null && lbi.IsMouseOver) {
                return lbi;
            }
        }

        return null;
    }
0 голосов
/ 02 ноября 2010

Это что-то вроде взлома, но я просто использовал событие PreviewMouseLeftButtonDown списка.

В обработчике мне пришлось спросить пользователя, уверены ли они, что хотят уйти. По какой-то причине, после появления окна сообщения, независимо от того, помечаете ли вы e.handled как true или нет, выбранное событие не будет запускаться, что-то в этом окне сообщений. Поэтому, если пользователь подтвердит навигацию, я бы использовал щелчок мышью, чтобы найти соответствующий элемент данных, по которому щелкнули (цикл с VisualTreeHelper, пока не найдете ListBoxItem), а затем выберите этот элемент вручную. Если пользователь решает не перемещаться, просто установите для e.handled значение false (хотя появление окна сообщения, по-видимому, имеет идентичный эффект.)

0 голосов
/ 10 мая 2010

Одним из решений было бы сделать ListBox и ListBoxItems не фокусируемыми, пока вы не будете готовы к тому, чтобы пользователь их изменил. Вот быстрый макет, который выполнил это:

XAML:

<StackPanel>
        <ListBox x:Name="LB">
            <ListBoxItem Focusable="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=Focusable}"  Content="item 1"/>
            <ListBoxItem Focusable="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=Focusable}" Content="item 2"/>
            <ListBoxItem Focusable="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=Focusable}" Content="item 3"/>
            <ListBoxItem Focusable="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=Focusable}" Content="item 4"/>
            <ListBoxItem Focusable="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=Focusable}" Content="item 5"/>
            <ListBoxItem Focusable="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=Focusable}" Content="item 6"/>
        </ListBox>
        <Button Content="Lock/Unlock" Click ="Button_Click"/>
    </StackPanel>

Код:

   private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (LB.Focusable == true)
            LB.Focusable = false;
        else
            LB.Focusable = true;
    }
0 голосов
/ 10 мая 2010

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

Этот простой шаг устраняет большую часть сложности выяснения того, что значение изменилось, и было ли оно допустимым изменением и т. Д. Если вы разрешите редактировать поле со списком (то есть значение, введенное в поле), это добавляет еще один уровень: сложность.

В противном случае, вот связанное обсуждение: Как предотвратить / отменить изменение значения поля со списком в c #?

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