首页 文章

处理WPF可编辑组合框在输入文本时不属于datsource

提问于
浏览
2

我在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;

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

Update:

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

3 回答

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

    您可以尝试处理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;
    }
    
  • 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文本的属性 .

    EDIT: 好了你需要做的就是去你的项目,右键单击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对象 .

相关问题