【问题标题】:Listbox's SelectionChanged event getting fired multiple times列表框的 SelectionChanged 事件被多次触发
【发布时间】:2014-09-23 09:35:50
【问题描述】:

我正在尝试在 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 事件将被抛出两次,依此类推。

【问题讨论】:

  • 为什么要在回调中删除和添加事件处理程序?
  • 因为我不希望在自动完成列表框填充最新列表之前选择列表框,反之亦然
  • private async void tb_TextChanged(object sender, TextChangedEventArgs e) 函数的try 块中添加列表框选择更改事件lb.SelectionChanged += lb_SelectionChanged; 之前,我通过删除列表框选择更改事件lb.SelectionChanged -= lb_SelectionChanged; jsut 解决了这个问题。但仍然不确定我之前做错了什么。

标签: c# xaml listbox windows-store-apps


【解决方案1】:

问题在于您删除/添加事件处理程序的代码与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 将被调用两次。

我不会使用这样的方案,让您一直在运行中添加/删除事件。一个简单的布尔变量应该会更好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-17
    • 2014-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-06
    • 2018-09-22
    相关资源
    最近更新 更多