c# - 列表框的 SelectionChanged 事件被多次触发

标签 c# xaml listbox windows-store-apps

我正在尝试在 Windows 8.1 应用程序中制作一个自动完成框。

Xaml 代码:

    <Grid Background="#CCFFFFFF" VerticalAlignment="Top"  >
        <TextBox x:Name="tb" IsTextPredictionEnabled="False" Margin="30" Height="50" PlaceholderText="Enter text" VerticalAlignment="Top"  Background="Transparent" BorderBrush="#333333" Foreground="#333333" FontWeight="SemiBold"  />
        <ListBox x:Name="lb" Background="Transparent" BorderBrush="#333333" MaxHeight="400" Visibility="Collapsed"   Margin=" 30 80 30 30" VerticalAlignment="Top" >
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="{Binding data}" Foreground="#333333"/>
                        <TextBlock Text="{Binding data1}" Grid.Column="1" Margin="10 0 10 0" Foreground="#333333"/>
                        <StackPanel Orientation="Horizontal" Grid.Column="2">
                            <TextBlock Text="{Binding data2}" Margin="10 0 10 0" Foreground="#333333" />
                            <TextBlock Text="{Binding data3}" Foreground="#333333" />
                        </StackPanel>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>

事件处理器:

        private async void tb_TextChanged(object sender, TextChangedEventArgs e)
        {
            lb.SelectionChanged -= lb_SelectionChanged;
            if (tb.Text.Length < 1 || String.IsNullOrWhiteSpace(this.tb.Text))
            {
                return;
            }
            try
            {
                var list = await Data.getData();
                lb.ItemsSource = list;
                lb.Visibility = Windows.UI.Xaml.Visibility.Visible;
                lb.SelectionChanged += lb_SelectionChanged;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message.ToString());
            }
        }
        void lb_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            tb.TextChanged -= tb_TextChanged;
            if (lb.SelectedItem == null)
            {
                tb.TextChanged += tb_TextChanged;
                lb.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
                return;
            }
            tb.Text = lb.SelectedItem.ToString();
            var item = (Data)lb.SelectedItem;
            lb.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
            tb.TextChanged += tb_TextChanged;
            System.Diagnostics.Debug.WriteLine("SelectionChanged Called\n");
        }

问题是,如果我在 textbox 中键入一个字符并从显示的 listbox 中选择一个项目,则会引发一次 SelctionChanged 事件.如果我键入两个字符,然后再次从显示的框中选择一个项目,则会引发两次 SelectionChanged 事件,依此类推。

最佳答案

问题是您结合 async 方法删除/添加了事件处理程序的代码。

设想以下情况:

  • 用户在文本框中输入字符:调用 tb_TextChanged,从 lb.SelectionChanged 中删除事件处理程序。然后调用 Data.GetData 并在安排继续后立即返回。
  • 用户在文本框中输入另一个字符:调用 tb_TextChanged,从 lb.SelectionChanged 中删除事件处理程序。然后调用 Data.GetData 并在安排继续后立即返回。
  • 第一次调用 Data.GetData 的结果可用,继续执行 lb_SelectionChanged 添加 lb.SelectionChanged 事件。
  • 第二次调用 Data.GetData 的结果可用,继续执行 lb_SelectionChanged 添加 lb.SelectionChanged 事件。

现在 SelectionChanged 有两个元素,您的 lb_SelectionChanged 将被调用两次。

我不会使用那种总是在运行中添加/删除事件的方案。一个简单的 bool 变量应该工作得更好。

关于c# - 列表框的 SelectionChanged 事件被多次触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25991684/

相关文章:

c# - 如何使用SDK V4在C#中修改WEBCHAT中BOT和USER输入的UI?

c# - IoC、工厂和构造函数参数

c# - 公式和数学表达式解析器算法

.net - 在 Label 的内容中明确使用 TextBlock 会使 ContentPresenter 行为异常

c# - 将按钮 XAML 更改为 C#

python - 当单击表单上的其他位置时,tkinter 列表框失去了选择

vb.net 列表框搜索

c# - 事件网格和 Notes 预览不同步,并且未显示正确的数据

c# - 如何在 Xamarin 表格 pcl 的网格中插入背景图像

Java Swing : Set member which is displayed in JListBox