Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Listbox的SelectionChanged事件被多次激发_C#_Xaml_Listbox_Windows Store Apps - Fatal编程技术网

C# Listbox的SelectionChanged事件被多次激发

C# Listbox的SelectionChanged事件被多次激发,c#,xaml,listbox,windows-store-apps,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" Ba

我正在尝试在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");
        }

问题是,如果我在文本框中键入一个字符并从显示的列表框中选择一个项目,则SelectChanged事件会引发一次。如果我键入两个字符,然后再次从显示的框中选择一个项目,则SelectionChanged事件将抛出两次,以此类推。

问题在于您将事件处理程序的代码与异步方法结合起来删除/添加

想象一下以下情况:

用户在文本框中输入字符:调用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将被调用两次


我不会使用这样的方案,即您随时动态添加/删除事件。一个简单的布尔变量应该工作得更好。

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