处理WPF可编辑组合框在输入文本时不是数据源的一部分

时间:2014-07-24 09:36:37

标签: c# wpf xaml combobox

我在WPF中有一个Combobox,我设置了Is Editable =“true”,它允许我在组合框中输入任何文本。我想限制用户输入数据源外的文本。

的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}" />

C#:

System.Data.DataView vw = tableAdapterServices.GetData().DefaultView;
service.ItemsSource = vw;
service.SelectedIndex = 0;

我不想让用户输入数据源中不存在的文本,或者在用户输入任何其他文本时处理它。

更新

感谢@Vishal解决方案,LostFocus事件处理问题,但它引发了另一个问题。我有一个按钮,用于将组合框值和其他文本框值一起提交给服务器。我在lostfocus事件中的组合框中设置默认值。但是,如果在组合框中添加了数据源值以外的其他值,我需要阻止按钮单击事件。

3 个答案:

答案 0 :(得分:2)

您可以在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;
    }
}

答案 1 :(得分:0)

您可以尝试处理ComboBox的TextInput或PreviewTextInput事件,自己进行文本搜索,选择最合适的项目,然后设置&#34; e.Handled = true。&#34; 这适用于单个字符(即如果您输入字母&#34; j&#34;,它将选择包含&#34; j&#34;或&#34; J&#34;)的第一个项目,但是我确定你的控制方法可以做到这一点。只需要包含更多逻辑即可实现这一目标。

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;
}

答案 2 :(得分:0)

好的,根据我的理解,如果数据源中没有包含结果字符串的项目,组合框的行为应该忽略插入的字符。

我相信你正在使用MVVM样式,因为你正在使用绑定。你可以做的是将ComboBox文本绑定到属性,将PreviewTextInput事件绑定到命令并在那里进行过滤。

<强> 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:

    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;
        }
    }

其中Items是包含项目的ObservableCollection(在这种情况下,它是一个字符串列表),Text是绑定到Combobox文本的属性。

编辑:好的,你需要做的就是去你的项目,右键点击References,选择Manage NuGet Packages,搜索并安装MVVM Light。以GalaSoft开头的两个dll将添加到您的引用中。在此之后,在您的xaml代码中添加以下命名空间:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"

这允许您执行的操作是将事件绑定到ICommand对象。