在WPF中取消设置组合框的选定文本

时间:2018-02-17 11:43:49

标签: c# wpf combobox

我有一个带有组合框的WPF应用程序,该组合框绑定到数据库调用。用户键入名称,数据库调用返回可能的名称匹配项。 我检查键入文本的长度,以确保键入至少4个字符以提高速度。

我遇到的问题是,在数据库调用返回其结果后,将选择组合框中的文本。此时用户继续键入它们将覆盖所选文本。 我尝试了很多东西,但在代码隐藏中设置选定的索引会产生部分结果。最初它不起作用,但后续搜索未选择文本。理想情况下,我想设置类似selectionLength = 0的东西,但我无法使用。

我的问题是如何阻止已经输入的组合框文本被选中?

xaml提取物:

<ComboBox 
            Grid.Column="2" 
            Grid.Row="1" 
            Height="30" 
            IsEditable="True"
            IsReadOnly="False"
            ItemsSource="{Binding PatientsCollection,UpdateSourceTrigger=PropertyChanged,NotifyOnTargetUpdated=True}"
            Name="SelectPatientCombobox" 
            SelectedValue="{Binding SelectedPatientId,Mode=Default}"
            SelectedValuePath="pat_pharmacy_patient_id" 
            TargetUpdated="SelectPatientCombobox_TargetUpdated"
            Text="{Binding SearchPatientText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
            VerticalAlignment="Top"
            Visibility="{Binding SelectPatientVisible, Converter={StaticResource BoolToVis}}"
            >
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <Grid Margin="0,0,0,0">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <Image Source="{Binding Path=PatientIcon}" MaxHeight="32" MaxWidth="32" Margin="0,2,5,2"
                           Grid.Column="0" Grid.RowSpan="2" />
                        <TextBlock Grid.Row="0" Grid.Column="1">
                        <Run Text="{Binding TitleFirstName, Mode=OneWay}" />
                        <Run Text=" " />
                        <Run FontWeight="Bold" Text="{Binding pat_name_last}" />
                        </TextBlock>
                        <StackPanel Grid.Row="1" Orientation="Horizontal" Grid.Column="1">
                            <TextBlock Foreground="SlateGray" Text="{Binding cod_addr1}" Margin="0,0,5,0" />
                            <TextBlock Foreground="SlateGray" Text="{Binding suburb}" Margin="0,0,5,0" />
                            <TextBlock Foreground="SlateGray" Text="{Binding postcode}" Margin="0,0,0,0" />
                        </StackPanel>
                    </Grid>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>

背后的代码:

        private void SelectPatientCombobox_TargetUpdated(object sender, DataTransferEventArgs e)
    {
        if ( false == ((ComboBox) sender).IsLoaded) return;
        ((ComboBox) sender).IsDropDownOpen = ((ComboBox) e.Source).Items.Count > 0;
        ((ComboBox)sender).SelectedIndex = -1;
    }

当数据库调用返回数据并将其转换为ObservableCollection时,ViewModel很复杂

1 个答案:

答案 0 :(得分:0)

如果其他人有同样的问题,请回答这个问题。这是一个黑客,但我无法找到一个更好的方法来正确解决问题。

在代码隐藏中,我以编程方式按右箭头键使文本未被选中。屏幕略有一点,您可以看到未选中的文本,但它可以正常工作。

所以后面的代码变成了:

    private void SelectPatientCombobox_TargetUpdated(object sender, DataTransferEventArgs e)
    {
        if ( false == ((ComboBox) sender).IsLoaded) return;
        if ((ComboBox)sender == null) return;
        ((ComboBox) sender).IsDropDownOpen = ((ComboBox) e.Source).Items.Count > 0;
        ((ComboBox)sender).SelectedIndex = -1;

        // when the result is returned, the text is highlighted.
        // typing when text is selected erases the text already typed.
        // so this total hack is a way to press the right arrow key after the results
        // come back so that the text is no longer selected.

        const Key key = Key.Right; // Key to send
        var target = Keyboard.FocusedElement;    // Target element
        var routedEvent = Keyboard.KeyDownEvent; // Event to send
        var inputSource = PresentationSource.FromVisual((ComboBox)sender);

        target.RaiseEvent(
            new KeyEventArgs(
                    Keyboard.PrimaryDevice,
                    inputSource,
                    0,
                    key)
                { RoutedEvent = routedEvent }
        );
    }