Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf 组合框仅通过鼠标或Enter键选择项目_Wpf_Combobox - Fatal编程技术网

Wpf 组合框仅通过鼠标或Enter键选择项目

Wpf 组合框仅通过鼠标或Enter键选择项目,wpf,combobox,Wpf,Combobox,我有一个WPF组合框 我需要更改弹出列表中的默认行为 现在,按up和down键SelectedItem会自动更改。 我需要更改SelectedItem,只需按Enter键或用鼠标单击即可 怎样才能做到呢 我对组合框进行了子类化: protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e) { Debug.Write("Pressed " + e.Key+ " "); if (e.Key

我有一个WPF
组合框

我需要更改弹出列表中的默认行为

现在,按
up
down
SelectedItem
会自动更改。
我需要更改
SelectedItem
,只需按
Enter
键或用鼠标单击即可

怎样才能做到呢

我对组合框进行了子类化

protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e)
{
    Debug.Write("Pressed " + e.Key+ " ");
    if (e.Key == System.Windows.Input.Key.Up || e.Key == System.Windows.Input.Key.Down)
    {
        // ???
        e.Handled = true;
        return;
    }
    base.OnPreviewKeyDown(e);
}
此代码不起作用-未显示弹出窗口,用户无法选择项目。 我应该写什么,在哪里?:)

谢谢

UPD1:

我需要与
组合框的
弹出窗口相同的功能,用户可以通过鼠标选择项目。
每个项目都可以用鼠标悬停,但不能被选中。选择仅通过按鼠标按钮才能变为。我也需要“向上”和“向下”仅突出显示弹出窗口中的项目,但只有按
Enter
或鼠标单击才能更改
SelectedItem

UPD2: 若我用鼠标按下按钮,那个么会在ComboCox中打开弹出窗口,我可以用鼠标突出显示弹出窗口中的项目,但SelectedItem只有在我点击项目时才会更改

我需要同样的键盘功能。如果我开始在ComboBox中输入一些内容,弹出窗口就会打开。我必须通过键盘向上和向下突出显示项目。组合框中的文本框在高亮显示期间不得更改,只有在我按[code>Enter
(或鼠标单击)时,SelectedItem才能更改

UPD3:
链接到演示解决方案:

您应该在组合框中的所有
组合框项目上处理此事件

   <ComboBox.Resources>
        <Style TargetType="{x:Type ComboBoxItem}">
           <EventSetter Event="PreviewKeyDown" Handler="OnPreviewKeyDown" />
        </Style> 
  </ComboBox.Resources>

希望这对您有所帮助。

您的代码似乎工作正常,在取消按键事件之前,只需添加一个检查以查看下拉列表是否打开即可

protected override void OnPreviewKeyDown(KeyEventArgs e)
{
    Debug.Write("Pressed " + e.Key + " ");
    if (!base.IsDropDownOpen && (e.Key == Key.Up || e.Key == Key.Down))
    {
        e.Handled = true;
        return;
    }
    base.OnPreviewKeyDown(e);
}

在我看来,您应该创建属性-IsKeyNavigation(比如IsMouseOver)


如果按了.Up键或.Down键,您应该定义导航元素并更改VisualState。

以下是对我有效的解决方案-

public class CustomComboBox : ComboBox
{
    private int _currentItemIndex;
    private string _rowColor = "#E7E7E7";
    private string _selectedRowColor = "#FFFFC6";        

    protected override void OnDropDownOpened(EventArgs e)
    {
        _currentItemIndex = base.SelectedIndex;
        base.OnDropDownOpened(e);
    }

    protected override void OnPreviewKeyDown(KeyEventArgs e)
    {
        if (base.IsDropDownOpen)
        {
            if (e.Key == Key.Up || e.Key == Key.Down)
            {
                ComboBoxItem currentItem;
                var colorConverter = new BrushConverter();

                if (_currentItemIndex > -1 && _currentItemIndex != base.SelectedIndex)
                {
                    currentItem = (ComboBoxItem)base.ItemContainerGenerator.ContainerFromIndex(_currentItemIndex);
                    currentItem.Background = (Brush)colorConverter.ConvertFromString(_rowColor);
                }

                if (e.Key == Key.Up)
                {
                    _currentItemIndex -= 1;
                    if (_currentItemIndex < 0)
                    {
                        _currentItemIndex = 0;
                    }
                }
                else if (e.Key == Key.Down)
                {
                    _currentItemIndex += 1;
                    if (_currentItemIndex > base.Items.Count - 1)
                    {
                        _currentItemIndex = base.Items.Count - 1;
                    }
                }

                currentItem = (ComboBoxItem)base.ItemContainerGenerator.ContainerFromIndex(_currentItemIndex);
                currentItem.Background = (Brush)colorConverter.ConvertFromString(_selectedRowColor);
                currentItem.BringIntoView();

                e.Handled = true;
                return;
            }
            else if (e.Key == Key.Enter)
            {
                base.SelectedItem = base.Items[_currentItemIndex];
            }
        }
        base.OnPreviewKeyDown(e);
    }

    protected override void OnDropDownClosed(EventArgs e)
    {
        if (_currentItemIndex > -1 && base.Items[_currentItemIndex] != base.SelectedItem)
        {
            var colorConverter = new BrushConverter();
            ComboBoxItem currentItem = (ComboBoxItem)base.ItemContainerGenerator.ContainerFromIndex(_currentItemIndex);
            currentItem.Background = (Brush)colorConverter.ConvertFromString(_rowColor);
        }
        base.OnDropDownClosed(e);
    }
}
公共类CustomComboBox:ComboBox
{
私有int_currentItemIndex;
私有字符串_rowColor=“#E7E7E7”;
私有字符串_selectedRowColor=“#FFFFC6”;
受保护的覆盖无效OnDropDownOpen(事件参数e)
{
_currentItemIndex=base.SelectedIndex;
底座。已向下打开(e);
}
PreviewKeyDown(KeyEventArgs e)上受保护的覆盖无效
{
if(基本IsDropDownOpen)
{
如果(e.Key==Key.Up | | e.Key==Key.Down)
{
ComboBoxItem当前项;
var colorConverter=新的BrushConverter();
如果(_currentItemIndex>-1&&u currentItemIndex!=base.SelectedIndex)
{
currentItem=(ComboBoxItem)base.ItemContainerGenerator.ContainerFromIndex(_currentItemIndex);
currentItem.Background=(画笔)colorConverter.ConvertFromString(_rowColor);
}
如果(e.Key==Key.Up)
{
_currentItemIndex-=1;
如果(_currentItemIndex<0)
{
_currentItemIndex=0;
}
}
else if(e.Key==Key.Down)
{
_currentItemIndex+=1;
如果(_currentItemIndex>base.Items.Count-1)
{
_currentItemIndex=base.Items.Count-1;
}
}
currentItem=(ComboBoxItem)base.ItemContainerGenerator.ContainerFromIndex(_currentItemIndex);
currentItem.Background=(画笔)colorConverter.ConvertFromString(_selectedRowColor);
currentItem.BringIntoView();
e、 已处理=正确;
返回;
}
else if(e.Key==Key.Enter)
{
base.SelectedItem=base.Items[_currentItemIndex];
}
}
基于预览的向下(e);
}
受保护的覆盖无效OnDropDownClosed(事件参数e)
{
if(\u currentItemIndex>-1&&base.Items[\u currentItemIndex]!=base.SelectedItem)
{
var colorConverter=新的BrushConverter();
ComboBoxItem currentItem=(ComboBoxItem)base.ItemContainerGenerator.ContainerFromIndex(_currentItemIndex);
currentItem.Background=(画笔)colorConverter.ConvertFromString(_rowColor);
}
底座。关闭(e);
}
}

最好使用组合框。OnDropDownClosed(EventArgs)方法

PS:对于Infrastics控件(UltraComboEditor),它是OnAfterCloseUp事件。

安装nuget软件包,创建如下类(注意:左/右箭头也会更改关闭的聚焦组合框中的选择):

公共类ComboxCustomBehavior:行为
{
私有只读ISet _dropdownblockeys=new HashSet{Key.Up,Key.Down,Key.Left,Key.Right};
受保护的覆盖无效附加()
{
AssociatedObject.PreviewKeyDown+=AssociatedObject\u键向下;
}
附加时受保护的覆盖无效()
{
AssociatedObject.PreviewKeyDown-=AssociatedObject\u键向下;
}
private void Associated object_KeyDown(对象发送方,KeyEventArgs e)
{
if(_dropdownblockeys.Contains(e.Key))
e、 已处理=正确;
//当您只需要在关闭的组合框上停止选择时,请使用以下行
//e.已处理=!((组合框)发送方)。IsDropDownOpen;
}
}
将此行为类添加到xaml:

<ComboBox>
    <ComboBoxItem>Item 1</ComboBoxItem>
    <ComboBoxItem>Item 2</ComboBoxItem>
    <ComboBoxItem>Item 3</ComboBoxItem>
    <i:Interaction.Behaviors>
        <local:ComboBoxCustomBehaviour />
    </i:Interaction.Behaviors>
</ComboBox>

项目1
项目2
项目3

我必须从子类
MyComboBox
类中执行,而不是在XAML中。有可能吗?我为您提供了XAML,您的处理程序可以在您的XAML.cs文件中,或者如果您使用的是MVVm,则可以通过附加的行为执行此操作。我没有XAML。我只有类MyComboBox:ComboBox,所以我不需要附加行为,因为
public class CustomComboBox : ComboBox
{
    private int _currentItemIndex;
    private string _rowColor = "#E7E7E7";
    private string _selectedRowColor = "#FFFFC6";        

    protected override void OnDropDownOpened(EventArgs e)
    {
        _currentItemIndex = base.SelectedIndex;
        base.OnDropDownOpened(e);
    }

    protected override void OnPreviewKeyDown(KeyEventArgs e)
    {
        if (base.IsDropDownOpen)
        {
            if (e.Key == Key.Up || e.Key == Key.Down)
            {
                ComboBoxItem currentItem;
                var colorConverter = new BrushConverter();

                if (_currentItemIndex > -1 && _currentItemIndex != base.SelectedIndex)
                {
                    currentItem = (ComboBoxItem)base.ItemContainerGenerator.ContainerFromIndex(_currentItemIndex);
                    currentItem.Background = (Brush)colorConverter.ConvertFromString(_rowColor);
                }

                if (e.Key == Key.Up)
                {
                    _currentItemIndex -= 1;
                    if (_currentItemIndex < 0)
                    {
                        _currentItemIndex = 0;
                    }
                }
                else if (e.Key == Key.Down)
                {
                    _currentItemIndex += 1;
                    if (_currentItemIndex > base.Items.Count - 1)
                    {
                        _currentItemIndex = base.Items.Count - 1;
                    }
                }

                currentItem = (ComboBoxItem)base.ItemContainerGenerator.ContainerFromIndex(_currentItemIndex);
                currentItem.Background = (Brush)colorConverter.ConvertFromString(_selectedRowColor);
                currentItem.BringIntoView();

                e.Handled = true;
                return;
            }
            else if (e.Key == Key.Enter)
            {
                base.SelectedItem = base.Items[_currentItemIndex];
            }
        }
        base.OnPreviewKeyDown(e);
    }

    protected override void OnDropDownClosed(EventArgs e)
    {
        if (_currentItemIndex > -1 && base.Items[_currentItemIndex] != base.SelectedItem)
        {
            var colorConverter = new BrushConverter();
            ComboBoxItem currentItem = (ComboBoxItem)base.ItemContainerGenerator.ContainerFromIndex(_currentItemIndex);
            currentItem.Background = (Brush)colorConverter.ConvertFromString(_rowColor);
        }
        base.OnDropDownClosed(e);
    }
}
public class ComboBoxCustomBehaviour: Behavior<ComboBox>
{
    private readonly ISet<Key> _dropdownBlockedKeys = new HashSet<Key>{Key.Up, Key.Down, Key.Left, Key.Right};

    protected override void OnAttached()
    {
        AssociatedObject.PreviewKeyDown += AssociatedObject_KeyDown;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.PreviewKeyDown -= AssociatedObject_KeyDown;
    }

    private void AssociatedObject_KeyDown(object sender, KeyEventArgs e)
    {
        if (_dropdownBlockedKeys.Contains(e.Key))
            e.Handled = true;
        // Use following line, when you need to stop selection only on closed ComboBox
        // e.Handled = !((ComboBox)sender).IsDropDownOpen;
    }
}
<ComboBox>
    <ComboBoxItem>Item 1</ComboBoxItem>
    <ComboBoxItem>Item 2</ComboBoxItem>
    <ComboBoxItem>Item 3</ComboBoxItem>
    <i:Interaction.Behaviors>
        <local:ComboBoxCustomBehaviour />
    </i:Interaction.Behaviors>
</ComboBox>