C# WPF:下拉组合框使文本高亮显示
当我在组合框中键入时,我会自动打开并启用下拉列表C# WPF:下拉组合框使文本高亮显示,c#,wpf,combobox,C#,Wpf,Combobox,当我在组合框中键入时,我会自动打开并启用下拉列表 searchComboBox.IsDropDownOpen = true; 这里的问题是-文本高亮显示,下一次击键将覆盖上一个文本 当ComboBox下拉菜单打开时,如何禁用文本突出显示?当comboxbox获得焦点时,您可以禁用文本突出显示(即在GotFocus事件中选择无文本)。但是,当您下拉组合框时,系统将在列表中找到该项并使其成为所选项。这会自动突出显示文本。如果我理解你所寻找的行为,我认为这是不完全可能的。迟到总比不迟到好,如果有人碰
searchComboBox.IsDropDownOpen = true;
这里的问题是-文本高亮显示,下一次击键将覆盖上一个文本
当ComboBox下拉菜单打开时,如何禁用文本突出显示?当comboxbox获得焦点时,您可以禁用文本突出显示(即在GotFocus事件中选择无文本)。但是,当您下拉组合框时,系统将在列表中找到该项并使其成为所选项。这会自动突出显示文本。如果我理解你所寻找的行为,我认为这是不完全可能的。迟到总比不迟到好,如果有人碰到这个问题,他可能会用这个 如果您覆盖组合框,则没有其他方法可以执行此操作。 首先获取模板中使用的文本框的句柄,并注册到selectionchanged事件
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var element = GetTemplateChild("PART_EditableTextBox");
if (element != null)
{
var textBox = (TextBox)element;
textBox.SelectionChanged += OnDropSelectionChanged;
}
}
private void OnDropSelectionChanged(object sender, RoutedEventArgs e)
{
// Your code
}
然后在事件处理程序中,您可以按照自己的意愿再次设置选择。在我的例子中,我在代码中调用IsDropDownOpen。将选择保存在那里,然后将其放回事件处理程序中。丑陋,但成功了 我也遇到了同样的问题,就像一些刚接触WPF的用户一样,我很难让Einar Guðsteinsson给出的解决方案发挥作用。因此,为了支持他的答案,我在这里粘贴了使其生效的步骤。(或者更准确地说,我是如何做到这一点的) 首先创建一个从combobox类继承的自定义combobox类。有关完整实现,请参见下面的代码。您可以在OnDropSelectionChanged中更改代码以满足您的个人需求 命名空间MyCustomComboxApp { 使用System.Windows.Controls
public class MyCustomComboBox : ComboBox
{
private int caretPosition;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var element = GetTemplateChild("PART_EditableTextBox");
if (element != null)
{
var textBox = (TextBox)element;
textBox.SelectionChanged += OnDropSelectionChanged;
}
}
private void OnDropSelectionChanged(object sender, System.Windows.RoutedEventArgs e)
{
TextBox txt = (TextBox)sender;
if (base.IsDropDownOpen && txt.SelectionLength > 0)
{
txt.CaretIndex = caretPosition;
}
if (txt.SelectionLength == 0 && txt.CaretIndex != 0)
{
caretPosition = txt.CaretIndex;
}
}
}
确保此自定义组合类存在于同一项目中。然后您可以使用下面的代码在UI中引用此组合
<Window x:Class="MyCustomComboBoxApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cc="clr-namespace:MyCustomComboBoxApp"
Title="MainWindow" Height="350" Width="525" FocusManager.FocusedElement="{Binding ElementName=cb}">
<Grid>
<StackPanel Orientation="Vertical">
<cc:MyCustomComboBox x:Name="cb" IsEditable="True" Height="20" Margin="10" IsTextSearchEnabled="False" KeyUp="cb_KeyUp">
<ComboBoxItem>Toyota</ComboBoxItem>
<ComboBoxItem>Honda</ComboBoxItem>
<ComboBoxItem>Suzuki</ComboBoxItem>
<ComboBoxItem>Vauxhall</ComboBoxItem>
</cc:MyCustomComboBox>
</StackPanel>
</Grid>
</Window>
丰田
本田
铃木
沃克斯霍尔
就这样!有任何问题,请提问!我会尽力帮助你的
感谢Einar Guðsteinsson的解决方案!我认为Andrew N提供的解决方案中缺少了一些东西,因为当我尝试时,文本框的选择更改事件将插入符号放置在错误的位置。因此我进行了此更改以解决此问题
namespace MyCustomComboBoxApp { using System.Windows.Controls;
public class MyCustomComboBox : ComboBox
{
private int caretPosition;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var element = GetTemplateChild("PART_EditableTextBox");
if (element != null)
{
var textBox = (TextBox)element;
textBox.SelectionChanged += OnDropSelectionChanged;
}
}
private void OnDropSelectionChanged(object sender, System.Windows.RoutedEventArgs e)
{
TextBox txt = (TextBox)sender;
if (base.IsDropDownOpen && txt.SelectionLength > 0)
{
caretPosition = txt.SelectionLength; // caretPosition must be set to TextBox's SelectionLength
txt.CaretIndex = caretPosition;
}
if (txt.SelectionLength == 0 && txt.CaretIndex != 0)
{
caretPosition = txt.CaretIndex;
}
}
}
根据clsturgeon的回答,我通过在发生DropdownOpen事件时设置选项解决了这个问题:
private void ItemCBox_DropDownOpened(object sender, EventArgs e)
{
TextBox textBox = (TextBox)((ComboBox)sender).Template.FindName("PART_EditableTextBox", (ComboBox)sender);
textBox.SelectionStart = ((ComboBox)sender).Text.Length;
textBox.SelectionLength = 0;
}
我可以使用Jun Xie修改的答案来修复它。假设您正在使用组合框搜索的
keyUp
事件,我在自定义用例中发现了一个仍然会覆盖文本的边缘用例:
- 第一次在组合框中键入。文本可以
- 使用向上和向下箭头键选择列表中的项目,但不要“提交”更改(例如,按enter键并关闭下拉选择。请注意,此时文本会高亮显示,就像clsturgeon指出的那样
- 再次尝试键入文本框。在这种情况下,文本将被覆盖,因为下拉列表仍然打开,因此事件从未触发以清除突出显示
另一种选择。防止框架与选择相混淆
public class ReflectionPreventSelectAllOnDropDown
{
private static readonly PropertyInfo edtbPropertyInfo;
static ReflectionPreventSelectAllOnDropDown()
{
edtbPropertyInfo = typeof(ComboBox).GetProperty("EditableTextBoxSite", BindingFlags.NonPublic | BindingFlags.Instance);
}
public void DropDown(ComboBox comboBox)
{
if (!comboBox.IsDropDownOpen)
{
var edtb = edtbPropertyInfo.GetValue(comboBox);
edtbPropertyInfo.SetValue(comboBox, null);
comboBox.IsDropDownOpen = true;
edtbPropertyInfo.SetValue(comboBox, edtb);
}
}
}
哪个“组合框下拉列表”你在说什么?你是否将组合框的IsTextSearchEnabled属性设置为false?它将禁用文本选择。希望这会有所帮助。你是对的?即使我使用asim提到的IsTextSearchEnabled属性设置为false,似乎也不可能。请你写出完整的代码,我有完全相同的问题,但我是新来的我的元素不是一个文本框而是一个组合框。你能在文本框中发布一个示例代码吗?它是这样的吗?文本框tb=(文本框)e.Source;if(tb!=null){tb.SelectionStart=0;}它是有效的,这是我找到的最短的解决方案,谢谢:d如果插入符号不在文本的末尾,这就不起作用了。很好地定位并修复Mohammed!第二个if语句除了设置未使用的caretPosition变量外,什么都不做。删除它,变量,然后在第一个if语句中指定一行-txt.CaretIndex=txt。选择长度
private void SearchBox_KeyUp(object sender, KeyEventArgs e)
{
SearchBox.IsDropDownOpen = true;
if (e.Key == Key.Down || e.Key == Key.Up)
{
e.Handled = true;
//if trying to navigate but there's noting selected, then select one
if(SearchBox.Items.Count > 0 && SearchBox.SelectedIndex == -1)
{
SearchBox.SelectedIndex = 0;
}
}
else if (e.Key == Key.Enter)
{
//commit to selection
}
else if (string.IsNullOrWhiteSpace(SearchBox.Text))
{
SearchBox.Items.Clear();
SearchBox.IsDropDownOpen = false;
SearchBox.SelectedIndex = -1;
}
else if (SearchBox.Text.Length > 1)
{
//if something is currently selected, then changing the selected index later will loose
//focus on textbox part of combobox and cause the text to
//highlight in the middle of typing. this will "eat" the first letter or two of the user's search
if(SearchBox.SelectedIndex != -1)
{
TextBox textBox = (TextBox)((ComboBox)sender).Template.FindName("PART_EditableTextBox", (ComboBox)sender);
//backup what the user was typing
string temp = SearchBox.Text;
//set the selected index to nothing. sets focus to dropdown
SearchBox.SelectedIndex = -1;
//restore the text. sets focus and highlights the combobox text
SearchBox.Text = temp;
//set the selection to the end (remove selection)
textBox.SelectionStart = ((ComboBox)sender).Text.Length;
textBox.SelectionLength = 0;
}
//your search logic
}
}
private void SearchBox_DropDownOpened(object sender, EventArgs e)
{
TextBox textBox = (TextBox)((ComboBox)sender).Template.FindName("PART_EditableTextBox", (ComboBox)sender);
textBox.SelectionStart = ((ComboBox)sender).Text.Length;
textBox.SelectionLength = 0;
}
public class ReflectionPreventSelectAllOnDropDown
{
private static readonly PropertyInfo edtbPropertyInfo;
static ReflectionPreventSelectAllOnDropDown()
{
edtbPropertyInfo = typeof(ComboBox).GetProperty("EditableTextBoxSite", BindingFlags.NonPublic | BindingFlags.Instance);
}
public void DropDown(ComboBox comboBox)
{
if (!comboBox.IsDropDownOpen)
{
var edtb = edtbPropertyInfo.GetValue(comboBox);
edtbPropertyInfo.SetValue(comboBox, null);
comboBox.IsDropDownOpen = true;
edtbPropertyInfo.SetValue(comboBox, edtb);
}
}
}