2

我有一个列表框,如果用户尚未完成某些任务,我想防止更改列表框的选择,这是我目前可以提供的最佳解释,在 WinForms 中曾经有选择更改并且它具有可取消的事件争论,在哪里即使更改选择,我们也可以捕获和取消。

我以为我会继承列表框并做一些事情,但是在内部,Selector 类中的所有功能都被隐藏了,我可以在反射器中看到,但是我无法继承和覆盖任何方法!

4

6 回答 6

4

我从 ListBox 派生了一个 MyListBox 类,并添加了名为 SelectionChanging 的事件,它是可取消的事件。然后我在 MyListBox 中使用 MyListBoxItem 作为 ItemContainer,它处理 Preview Left Mouse Up 事件并引发选择更改事件,在取消值时,我将事件标记为已处理,这可以防止新的选择以及它允许​​我通知用户做一些事情。

于 2010-06-21T07:50:58.273 回答
1

绑定IsSelected到视图模型类中的属性,并在属性的设置器中处理案例,例如:

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

请注意,PropertyChanged即使属性没有更改,您也会引发事件,因为从视图的角度来看,它确实发生了变化。

于 2010-05-10T17:36:36.037 回答
0

我知道这并不能直接回答您的问题,但在大多数情况下(我需要确信有理由不这样做),在满足选择标准之前,我根本无法控制。

这个简单的步骤消除了确定值是否已更改以及是否为有效更改等的大部分复杂性。如果您允许编辑组合框(即输入的值),则会增加另一个级别的复杂性。

否则,这里有一个相关的讨论: How to prevent/cancel a combobox's value change in c#?

于 2010-05-10T14:26:22.363 回答
0

一种解决方案是使 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;
    }
于 2010-05-10T14:46:35.607 回答
0

这有点小技巧,但我只是使用了列表框的 PreviewMouseLeftButtonDown 事件。

在处理程序中,我不得不询问用户是否确定要离开。出于某种原因,在弹出消息框后,无论您是否将 e.handled 标记为 true,都不会触发所选事件,这与该消息框有关。因此,如果用户确认导航,我将使用鼠标单击来查找被点击的相应数据项(使用 VisualTreeHelper 循环,直到找到 ListBoxItem),然后手动选择该项目。如果用户选择不离开,只需将 e.handled 设置为 false (尽管弹出消息框似乎具有相同的效果。)

于 2010-11-02T16:13:02.730 回答
0

当不满足某些条件时,我有同样的需求(询问用户是否真的想更改单个选择列表框中的选定项目)。单选很重要,否则代码会变得更复杂。我的解决方案基于 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;
    }
于 2015-03-23T18:18:18.087 回答