Reputation: 1031
I need to set my MenuFlyout
in a programmatical way. However, I notice that with the async code added to my function, the MenuFlyout
doesn't show its items unless I right click the item for the second time. How can I set my MenuFlyout
in an async way?
private async void MenuFlyout_Opened(object sender, object e)
{
var flyout = sender as MenuFlyout;
Music music = flyout.Target.DataContext as Music;
if (await Helper.FileNotExist(music.Path))
{
if (Removable)
{
flyout.Items.Clear();
flyout.Items.Add(MenuFlyoutHelper.GetRemovableMenuFlyoutItem(music, this));
}
else
{
Helper.ShowAddMusicResultNotification(music.Name);
}
return;
}
if (Removable) MenuFlyoutHelper.SetRemovableMusicMenu(sender, this);
else MenuFlyoutHelper.SetMusicMenu(sender, this);
if (AllowReorder)
{
var item = new MenuFlyoutItem()
{
Text = Helper.Localize("Move To Top"),
Icon = new SymbolIcon(Symbol.Upload)
};
item.Click += (s, args) =>
{
MediaHelper.MoveMusic(music.Index, 0);
};
flyout.Items.Add(item);
}
}
One way is to avoid using async code in such functions and to check if file exists in the Click
event of the items. But I have too many items. I think this is a bad idea.
This code works properly:
private void OpenMusicMenuFlyout(object sender, object e)
{
if (Removable) MenuFlyoutHelper.SetRemovableMusicMenu(sender, this);
else MenuFlyoutHelper.SetMusicMenu(sender, this);
if (AllowReorder)
{
var flyout = sender as MenuFlyout;
var item = new MenuFlyoutItem()
{
Text = Helper.Localize("Move To Top"),
Icon = new SymbolIcon(Symbol.Upload)
};
item.Click += (s, args) =>
{
Music music = (s as MenuFlyoutItem).DataContext as Music;
MediaHelper.MoveMusic(music.Index, 0);
};
flyout.Items.Add(item);
}
}
Code with Dispatcher.RunAsync
:
private async void OpenMusicMenuFlyout(object sender, object e)
{
var flyout = sender as MenuFlyout;
Music music = flyout.Target.DataContext as Music;
if (await Helper.FileNotExist(music.Path))
{
if (Removable)
{
flyout.Items.Clear();
flyout.Items.Add(MenuFlyoutHelper.GetRemovableMenuFlyoutItem(music, this));
}
else
{
Helper.ShowAddMusicResultNotification(music.Name);
}
return;
}
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () =>
{
if (Removable) MenuFlyoutHelper.SetRemovableMusicMenu(sender, this);
else MenuFlyoutHelper.SetMusicMenu(sender, this);
if (AllowReorder)
{
var item = new MenuFlyoutItem()
{
Text = Helper.Localize("Move To Top"),
Icon = new SymbolIcon(Symbol.Upload)
};
item.Click += (s, args) =>
{
MediaHelper.MoveMusic(music.Index, 0);
};
flyout.Items.Add(item);
}
});
}
Upvotes: 0
Views: 404
Reputation: 32775
Great question, for the testing, if we call async function in above OpenMusicMenuFlyout
event handler, MenuFlyout
Add operation will be interrupted, and UI rendering will be canceled. For above scenario, the better way is make Flyout
as ContextFlyout
content then use ListView
to replace MenuFlyout
. For more please check the following.
<SwipeControl>
<SwipeControl.ContextFlyout>
<Flyout Opening="OpenMusicMenuFlyout">
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Flyout>
</SwipeControl.ContextFlyout>
</SwipeControl>
Code Behind
private async void OpenMusicMenuFlyout(object sender, object e)
{
var items = new ObservableCollection<string>() { "One", "Two", "Three" };
var flyout = sender as Flyout;
var menu = flyout.Content as ItemsControl;
await TestMetod();
menu.ItemsSource = items;
}
Upvotes: 0