当输入的文本不是数据源的一部分时处理 WPF 可编辑组合框
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24930147/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Handling WPF Editable combobox when entered text is not a part of datsource
提问by Arti
I have a Combobox in WPF, I have set Is Editable="true" which allows me enter any text in the combobox. I would like to restrict users from entering text outside datasource.
我在 WPF 中有一个组合框,我设置了 Is Editable="true" 允许我在组合框中输入任何文本。我想限制用户在数据源之外输入文本。
Xaml:
Xml:
<ComboBox Name="service" Margin="0,0,0,4"
IsEditable="True"
Grid.Column="1"
Grid.ColumnSpan="2" Grid.Row="4"
SelectedValuePath="Id"
DisplayMemberPath="Service"
SelectedValue="{Binding Controller.Service1}"
ItemsSource="{Binding}" />
C#:
C#:
System.Data.DataView vw = tableAdapterServices.GetData().DefaultView;
service.ItemsSource = vw;
service.SelectedIndex = 0;
I do not want to allow users to enter text which is not present in the datasource, or handle it if the user enters any other text.
我不想让用户输入数据源中不存在的文本,或者在用户输入任何其他文本时处理它。
Update:
更新:
Thanks for the solution @Vishal, LostFocus event is handling the issue, but it gave rise to another issue. I have a button which is used to submit the combobox value along with other textbox values to the server. I am setting default value in the combobox in lostfocus event. But I need to prevent the button click event if some value other that datasource value is added in combobox.
感谢@Vishal 的解决方案,LostFocus 事件正在处理该问题,但它引发了另一个问题。我有一个按钮,用于将组合框值与其他文本框值一起提交到服务器。我在 lostfocus 事件的组合框中设置默认值。但是,如果在组合框中添加了该数据源值以外的某些值,我需要阻止按钮单击事件。
采纳答案by Vishal
You can check for selectedIndex in Lostfocus event :
您可以在 Lostfocus 事件中检查 selectedIndex :
private void ComboBox_LostFocus(object sender, EventArgs e)
{
if(((ComboBox)sender).SelectedIndex == -1)
{
//Text entered by user is not a part your ItemsSource's Item
SaveButton.IsEnabled = false;
}
else
{
//Text entered by user is a part your ItemsSource's Item
SaveButton.IsEnabled = true;
}
}
回答by Titanium
Ok, from what I understand the behaviour of the combobox should disregard an inserted character if there is no item in the datasource that contains the resulted string.
好的,根据我的理解,如果数据源中没有包含结果字符串的项目,组合框的行为应该忽略插入的字符。
I believe you are doing it in a MVVM style since you are using binding. What you can do is to bind the ComboBox text to a property and the PreviewTextInput event to a command and do the filtering there.
我相信您使用的是 MVVM 风格,因为您使用的是绑定。您可以做的是将 ComboBox 文本绑定到一个属性,并将 PreviewTextInput 事件绑定到一个命令,并在那里进行过滤。
XAML:
XAML:
<ComboBox Name="service"
Margin="0,0,0,4"
IsEditable="True"
Grid.Column="1"
Grid.ColumnSpan="2"
Grid.Row="4"
SelectedValuePath="Id"
DisplayMemberPath="Service"
SelectedValue="{Binding Controller.Service1}"
ItemsSource="{Binding}"
Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
>
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewTextInput">
<cmd:EventToCommand Command="{Binding TextInputCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Combobox>
C#ViewModel:
C#视图模型:
public RelayCommand<object> TextInputCommand { get; set; }
public bool CanExecuteTextInputCommand(object param)
{
return true;
}
public void ExecuteTextInputCommand(object param)
{
TextCompositionEventArgs e = param as TextCompositionEventArgs;
string currentText = this.Text;
string entireText = string.Format("{0}{1}", currentText, e.Text);
var item = this.Items.Where(d => d.StartsWith(entireText)).FirstOrDefault();
if (item == null)
{
e.Handled = true;
this.Text = currentText;
}
}
Where Itemsis the ObservableCollection containing the items (in this case it's a list of strings) and Textis the property binded to the Combobox text.
Items包含项目的 ObservableCollection在哪里(在本例中是字符串列表),并且Text是绑定到组合框文本的属性。
EDIT:Ok so what you need to do to make it work is to go to your project, right click on References, choose Manage NuGet Packages, search and install MVVM Light. Two dlls that start with GalaSoftwill be added to your references. After this, in your xaml code add these namespaces:
编辑:好的,所以你需要做的是让它工作是去你的项目,右键单击引用,选择管理 NuGet 包,搜索并安装MVVM Light. 以 开头的两个 dllGalaSoft将添加到您的引用中。在此之后,在您的 xaml 代码中添加这些命名空间:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
What this allows you to do is to bind an event to a ICommand object.
这允许您做的是将事件绑定到 ICommand 对象。
回答by Nomi Ali
You can try handling the ComboBox's TextInput or PreviewTextInput events, doing the text search yourself, selecting the most appropriate item, and setting "e.Handled = true." This works for a single character (i.e. if you enter the letter "j", it will select the first item that contains a "j" or "J"), but I'm sure there's a way to do this with your control. Just include a little more logic to achieve this.
您可以尝试处理 ComboBox 的 TextInput 或 PreviewTextInput 事件,自己进行文本搜索,选择最合适的项目,并设置“e.Handled = true”。这适用于单个字符(即,如果您输入字母“j”,它将选择包含“j”或“J”的第一个项目),但我确信有一种方法可以通过您的控件执行此操作。只需包含更多逻辑即可实现此目的。
private void MyComboBox_PreviewTextInput(object sender, TextCompositionEventArgs e) {
foreach (ComboBoxItem i in MyComboBox.Items) {
if (i.Content.ToString().ToUpper().Contains(e.Text.ToUpper())) {
MyComboBox.SelectedItem = i;
break;
}
}
e.Handled = true;
}

