在方法中间显示列表视图,但在方法继续之前等到 SelectionChanged 事件触发

Show listview in middle of method but wait until SelectionChanged event fires before method continues

Windows C# 中的 UWP 应用程序。我有一个检查条件的方法,根据条件,它可能需要向用户显示列表视图,以便他们可以 select 列表中的项目。在我可能显示需要 运行 的列表视图之后,我在方法中有更多代码。但是,因为列表视图显示并且我必须等待 SelectionChanged 事件处理程序触发,所以我不知道如何暂停该行上的调用方法,直到 SelectionChanged 的​​事件处理程序完成。我还没有写代码,所以这里有一些伪代码来说明:

private void LookupEmployee(string searchCriteria)
{
     List<string> matches = GetEmployeeNameMatchesFromCriteria(searchCriteria);

     if(matches.Count == null || matches.Count == 0)
     {
         //No matches found, warn user
         return;
     }
     if(matches.Count == 1)
     {
         //We are good, we have just one match which is desirable.
     }
     if(matches.Count > 1)
     {
         //This means we have more than one match and we need to popup list view to have user select one
         ShowListView(matches);
     }

     //Process Employee data here.
}

我知道一个选择是 "daisy chain" 通过将员工数据的最终处理分解为另一种方法来调用,并从列表视图的 SelectionChanged 事件处理程序中调用它。然而,这有两个问题。首先,如果我只有一个匹配项,那么无论如何我都不会显示列表视图或获取 SelectionChanged。其次,如果我在方法开始时有一堆变量和其他东西要在方法结束时使用,我不想(我也不知道如何)将所有这些传递过来并返回我需要显示的事件中的事件处理程序。

我想我在某种程度上寻找的是 MessageDialog 的处理方式。

 var md = new MessageDialog("My Message");

 md.Commands.Add(new UICommand("Okay")
 {

 });

 var result = await md.ShowAsync();

 if (result.Label == "Okay")
 {
     DoStuff;
 }

哪里用这个会等在线:

等待md.ShowAsync();

直到用户单击按钮,此时该方法可以从那里继续。

我想我正在寻找类似的东西,在我需要显示列表视图直到用户 selects 和项目并抓住项目的情况下,我可以保持在方法的行上那是 selected.

想法?

谢谢!

好的,我想我找到了我要找的东西,所以我想 post 代码。这类似于模式 window 在过去的工作方式。基本上,您可以使用 ContentDialog,它允许您在其中 "wrap" 任何您想要的控件。在我的例子中,我想显示一个 ListView,所以我将它包装在 ContentDialog 中。这是我拥有的:

  1. 首先我们可以做我们的测试,如果需要,我们可以根据测试创建 ContentDialog/ListView。如果我们确实创建了 ContentDialog,我们还可以设置 Display 参数,使其符合我们的要求。

    private async void checkProductMatches()
    {
        var selectedItem = string.Empty;
    
        //Check our results from DB.
        if (productResults.Count == 0)
        {
            //This means we didn't find any matches, show message dialog
        }
        if (productResults.Count == 1)
        {
            //We found one match, this is ideal. Continue processing.
            selectedItem = productResults.FirstOrDefault().Name;
        }
        if (productResults.Count > 1)
        {
            //Multiple matches, need to show ListView so they can select one.
            var myList = new ListView
            {
                ItemTemplate = Create(),
                ItemsSource =
                    productResults,
                    HorizontalAlignment = HorizontalAlignment.Stretch,
                    VerticalAlignment = VerticalAlignment.Stretch
            };
    
            var bounds = Window.Current.Bounds;
            var height = bounds.Height;
            var scroll = new ScrollViewer() { HorizontalAlignment = HorizontalAlignment.Stretch, VerticalAlignment = VerticalAlignment.Stretch, Height = height - 100 };
    
            var grid = new StackPanel();
            grid.Children.Add(myList);
            scroll.Content = grid;
            var dialog = new ContentDialog { Title = "Title", Content = scroll };
    
  2. 现在,我们连接 ListView SelectionChanged 事件的事件处理程序,并在该事件引发时获取 selectedItem。

            myList.SelectionChanged += delegate (object o, SelectionChangedEventArgs args)
            {
                if (args.AddedItems.Count > 0)
                {
                    MyProducts selection = args.AddedItems[0] as MyProducts;
                    if (selection != null)
                    {
                        selectedItem = selection.Name;
                    }
                }
                dialog.Hide();
            };
    
  3. 最后,我们等待内容对话框的显示。

            var s = await dialog.ShowAsync();
    

这样做的目的是,如果我们只有一项,则无需弹出内容对话框。因此,我们可以将一个结果分配给 selectedItem 变量并继续。但是,如果我们有多个匹配项,我们希望为用户显示一个列表 select 其中一项。在本例中,我们创建了 ContentDialog、ListView 和显示参数。他们的关键是在我们调用显示对话框和事件处理程序内部之前连接事件处理程序,我们确保取消或关闭对话框。然后我们调用等待对话框显示。这将在显示对话框时暂停在该行上执行此方法。一旦用户 selects 一个项目,事件处理程序将引发,获取 selected 项目,然后关闭对话框,这将允许该方法从等待的行继续执行。

完整方法如下:

    private async void checkProductMatches()
    {
        var selectedItem = string.Empty;

        //Check our results from DB.
        if (productResults.Count == 0)
        {
            //This means we didn't find any matches, show message dialog
        }
        if (productResults.Count == 1)
        {
            //We found one match, this is ideal. Continue processing.
            selectedItem = productResults.FirstOrDefault().Name;
        }
        if (productResults.Count > 1)
        {
            //Multiple matches, need to show ListView so they can select one.
            var myList = new ListView
            {
                ItemTemplate = Create(),
                ItemsSource =
                    productResults,
                    HorizontalAlignment = HorizontalAlignment.Stretch,
                    VerticalAlignment = VerticalAlignment.Stretch
            };

            var bounds = Window.Current.Bounds;
            var height = bounds.Height;
            var scroll = new ScrollViewer() { HorizontalAlignment = HorizontalAlignment.Stretch, VerticalAlignment = VerticalAlignment.Stretch, Height = height - 100 };

            var grid = new StackPanel();
            grid.Children.Add(myList);
            scroll.Content = grid;
            var dialog = new ContentDialog { Title = "Title", Content = scroll };

            myList.SelectionChanged += delegate (object o, SelectionChangedEventArgs args)
            {
                if (args.AddedItems.Count > 0)
                {
                    MyProducts selection = args.AddedItems[0] as MyProducts;
                    if (selection != null)
                    {
                        selectedItem = selection.Name;
                    }
                }
                dialog.Hide();
            };

            var s = await dialog.ShowAsync();
        }

        //Test furter execution. Ideally, selected item will either be the one record or we will 
        //get here after the list view allows user to select one.
        var stringTest = string.Format("Selected Item: {0}", selectedItem);
    }

希望这对某人有所帮助。