【问题标题】:How do I prevent keyboard navigation in an AutoCompleteBox from firing the SelectionChanged event?如何防止 AutoCompleteBox 中的键盘导航触发 SelectionChanged 事件?
【发布时间】:2013-08-15 00:14:45
【问题描述】:

我正在尝试使用 WPF 工具包中的 AutoCompleteBox 构建搜索字段。 AutoCompleteBox 的 Text 属性绑定到实现 INotifyPropertyChangedViewModel 中的一个属性。当属性发生变化时,它会获取新的建议以显示给用户。

如果用户在选择一个之前使用箭头键扫描自动完成建议列表,则会出现问题 - 光标移动到弹出窗口的那一刻,SelectionChanged 被触发,文本字段获得一个新值,并且自动完成建议被重新收集。这也妨碍了我使用SelectionChanged 事件开始搜索的愿望。

有什么方法可以防止在键盘导航时触发 SelectionChanged 事件?

这就是我的设置方式。注意sc:SearchFieldAutoCompleteBox 的子类,它只提供一种访问AutoCompleteBox 上的TextBox 属性的方法,因此我可以调用SelectAll() 之类的函数

XAML:

<sc:SearchField x:Name="SearchField" DataContext="{Binding SearchBoxVm}" Text="{Binding Query, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding QuerySuggestions, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" IsTextCompletionEnabled="False" Margin="54,10,117,67" Grid.RowSpan="2" BorderThickness="0" FontSize="14" PreviewKeyUp="searchField_OnKeyup" Foreground="{Binding Foreground, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontStyle="{Binding QueryFont, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
        </sc:SearchField>

视图模型:

void GetQuerySuggestions()
{
    if (!string.IsNullOrEmpty(Query) && !Query.Equals(DEFAULT_TEXT))
    {
        QueryFont = FontStyles.Normal;
        Foreground = Brushes.Black;
        QuerySuggestions = SearchAssistant.GetQueryRecommendations(_query);
    }
}

public string _query = DEFAULT_TEXT;
public string Query
{
    get
    {
        return _query;
    }
    set
    {
        _query = value;
        GetQuerySuggestions();
        NotifyPropertyChanged("Query");
    }
}

List<string> querySuggestions = new List<string>();
public List<string> QuerySuggestions
{
    get { return querySuggestions; }
    set
    {
        querySuggestions = value;
        NotifyPropertyChanged("QuerySuggestions");
    }
}

SearchField 子类:

public class SearchField : AutoCompleteBox
{
    public TextBox TextBox 
    { 
        get 
        {
            return (this.GetTemplateChild("Text") as TextBox);
        } 
    }        
}

【问题讨论】:

    标签: wpf xaml autocomplete wpftoolkit selectionchanged


    【解决方案1】:

    不确定这是否是您想要做的,但我有以下代码,仅在按下“Enter”键或使用鼠标从列表中选择项目时更改选择(单击鼠标左键)。我可以毫无问题地在列表中上下箭头,并且仅在用户按下回车键或单击所需条目时触发选择更改事件。

    请注意,我使用的是 AutoCompleteBox,而不是您使用的 SearchField。

    在 XAML 中:

    <toolkit:AutoCompleteBox Name="OmniSearchTextBox"
                             ItemsSource="{Binding CompanyList}" 
                             SelectedItem="{Binding SelectedObject, Mode=TwoWay}"
                             IsTextCompletionEnabled="False" 
                             FilterMode="Contains" 
                             KeyUp="OmniSearch_KeyUp"
                             MouseLeftButtonUp="OmniSearch_MouseLeftButtonUp"
                             Margin="10,94,10,0" 
                             RenderTransformOrigin="0.518,1.92" Height="35"
                             VerticalAlignment="Top" />
    

    在后面的代码中:

    private void OmniSearch_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter)
        {
            BindingExpression exp = this.OmniSearchTextBox.GetBindingExpression(AutoCompleteBox.SelectedItemProperty);
            exp.UpdateSource();
        }
    }
    
    private void OmniSearch_MouseLeftButtonUp(object sender, MouseEventArgs e)
    {
        BindingExpression exp = this.OmniSearchTextBox.GetBindingExpression(AutoCompleteBox.SelectedItemProperty);
        exp.UpdateSource();
    }
    

    在 ViewModel 中:

    private const string CompanyListPropertyName = "CompanyList";
    private ObservableCollection<Company> _companyList;
    public ObservableCollection<Company> CompanyList
    {
        get
        {
            return _companyList;
        }
        set
        {
            if (_companyList == value)
            {
                return;
            }
    
            _companyList = value;
            RaisePropertyChanged(CompanyListPropertyName);
        }
    
    }
    
    private Company _selectedObject;
    public Company SelectedObject
    {
        get
        {
            return _selectedObject;
        }
        set
        {
            if (_selectedObject != value)
            {
                _selectedObject = value;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-22
      • 2013-10-23
      • 1970-01-01
      相关资源
      最近更新 更多