【问题标题】:WinRT call Flyout.ShowAt() asyncWinRT 调用 Flyout.ShowAt() 异步
【发布时间】:2015-11-02 21:59:08
【问题描述】:

我正在构建我自己的带有列表选择的Flyout 控件,以便在Windows Phone 和Windows 桌面上使用它。与ListPickerFlyout 类不同,Flyout 类没有显示浮出控件的异步方法。

如何调用 ShowAt 方法异步并在弹出关闭后返回选定的值?


解决方案:

使用TaskCompletionSource<T> 可以实现异步行为(感谢AwaitableUI libary)。仍然困扰我的是我必须在构造函数中手动创建 ListView。如果我可以改用 XAML 并只分配一个模板,那就太好了,但我没有找到可行的方法。

public class ListPickerFlyout<T> : Flyout where T : class
{
    private event EventHandler<object> ItemPicked;

    public ListPickerFlyout(IEnumerable<T> items)
    {
        Placement = FlyoutPlacementMode.Full;
        Opening += OnOpening;
        Closed += OnClosed;

        var listView = new ListView();
        listView.SelectionMode = ListViewSelectionMode.None;
        listView.IsItemClickEnabled = true;
        listView.ItemClick += OnItemClick;
        listView.DisplayMemberPath = "Name";
        listView.SetBinding(ListView.ItemsSourceProperty, new Binding { Source = items });

        Content = listView;
    }

    public async Task<T> ShowAsync()
    {
        this.ShowAt(Window.Current.Content as Frame);

        var tcs = new TaskCompletionSource<T>();

        EventHandler<object> eventHandler = null;

        eventHandler = (s, e) =>
        {
            this.Closed -= eventHandler;
            this.ItemPicked -= eventHandler;

            tcs.SetResult(e as T);
        };

        this.Closed += eventHandler;
        this.ItemPicked += eventHandler;

        return await tcs.Task;
    }

    private void OnItemClick(object sender, ItemClickEventArgs e)
    {
        var selectedItem = e.ClickedItem as T;

        var eventHandler = ItemPicked;
        if (eventHandler != null)
            eventHandler(this, selectedItem);

        this.Hide();
    }

    private void OnOpening(object sender, object e)
    {
        var frame = Window.Current.Content as Frame;
        var page = frame.Content as Page;

        if (page != null)
            page.BottomAppBar.Visibility = Visibility.Collapsed;
    }

    private void OnClosed(object sender, object e)
    {
        var frame = Window.Current.Content as Frame;
        var page = frame.Content as Page;

        if (page != null)
            page.BottomAppBar.Visibility = Visibility.Visible;
    }
}

【问题讨论】:

  • 你试过return new Task&lt;Item&gt;(() =&gt; ShowAt(Window.Current.Content as Frame)); 只是想不通,语法可能略有不同,因为我不确定 ShowAt 在选择后是否返回,但你可以做一个更复杂的任务在那里。
  • 是的,我已经尝试过了,但它应该会在Closed 事件引发时返回。

标签: c# windows-runtime async-await winrt-async flyout


【解决方案1】:

WinRT XAML 工具包具有可等待 UI 的概念,这使得等待许多通常不应用可等待逻辑的 UI 元素成为可能。我还没有在 Flyout 上尝试过,但它可能会起作用。

你可以找到它here

【讨论】:

    【解决方案2】:

    与后端工作不同,ShowAt 是一种 UI 交互。 PickerFlyout 类具有 ShowAtAsync 方法,但它不用于“等待”选择器结果。

    在 XAML 开发中,异步方法通常是为了避免 UI 阻塞。 而对于用户交互部分,我推荐使用事件驱动模式。

    在这种情况下,我建议在“已关闭”事件处理程序中检索选择项。

    【讨论】:

    • 我更新了我的问题。 ListPickerFlyout 有一个异步 ShowAt 方法,它返回选定的项目。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    • 2012-08-04
    • 1970-01-01
    • 1970-01-01
    • 2018-12-10
    • 2013-02-13
    相关资源
    最近更新 更多