mylim
mylim

Reputation: 313

UWP C# Menuflyout Unable To Display Item Properly During 1st Click

I am having an issue with my code to add button from json where the first attempt i click add button, the menuflyout won't have any respond but second click attempt then it will work properly. Can advise did i do anything wrong? Thanks.

private async void AddButton_Click(object sender, RoutedEventArgs e)
{
    List<ClientList> clientLists;
    var jsonSerializer = new DataContractJsonSerializer(typeof(List<ClientList>));


    var myStream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(CLIENTSLIST);

    clientLists = (List<ClientList>)jsonSerializer.ReadObject(myStream);
    var menuFlyout = new MenuFlyout();

    int isEmpty = myGrid.Children.Count;
    if (isEmpty == 0)
    {
        foreach (var device in clientLists)
        {
            var menuFlyoutItem = new MenuFlyoutItem() { Name = device.clientname, Text = device.clientname };
            menuFlyoutItem.Tag = device.clientaddress;
            menuFlyoutItem.Click += AddMenuFlyoutItem_Click;
            menuFlyout.Items.Add(menuFlyoutItem);
        }
    }else
    {
        foreach (var device in clientLists)
        {
            bool toAddButton = true;
            foreach (Button btn in myGrid.Children.OfType<Button>())
            {
                if (btn.Content.ToString() == device.clientname)
                {
                    toAddButton = false;
                }
            }
            if (toAddButton)
            {
                var menuFlyoutItem = new MenuFlyoutItem() { Name = device.clientname, Text = device.clientname };
                menuFlyoutItem.Tag = device.clientaddress;
                menuFlyoutItem.Click += AddMenuFlyoutItem_Click;
                menuFlyout.Items.Add(menuFlyoutItem);
            }
        }
    }
    AddButton.Flyout = menuFlyout;
}

Upvotes: 0

Views: 79

Answers (1)

Martin Zikmund
Martin Zikmund

Reputation: 39082

The problem is you are loading the data asynchronously here:

var myStream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(CLIENTSLIST);

When this happens, UI continues executing the Click event, so the button is clicked (and Flyout is null the first time) and Flyout will never display. You should rather load the Flyout before that - either when the page loads or when the data source changes, so that when the user clicks, the flyout is already there. Doing loading in Click is simply too late, if you need an asynchronous operation to finish.

Alternatively you could set the flyout right at the start:

private async void AddButton_Click(object sender, RoutedEventArgs e)
{
    var menuFlyout = new MenuFlyout();
    AddButton.Flyout = menuFlyout;
    List<ClientList> clientLists;
    var jsonSerializer = new DataContractJsonSerializer(typeof(List<ClientList>));


    var myStream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(CLIENTSLIST);

    clientLists = (List<ClientList>)jsonSerializer.ReadObject(myStream);

    int isEmpty = myGrid.Children.Count;
    if (isEmpty == 0)
    {
        foreach (var device in clientLists)
        {
            var menuFlyoutItem = new MenuFlyoutItem() { Name = device.clientname, Text = device.clientname };
            menuFlyoutItem.Tag = device.clientaddress;
            menuFlyoutItem.Click += AddMenuFlyoutItem_Click;
            menuFlyout.Items.Add(menuFlyoutItem);
        }
    }else
    {
        foreach (var device in clientLists)
        {
            bool toAddButton = true;
            foreach (Button btn in myGrid.Children.OfType<Button>())
            {
                if (btn.Content.ToString() == device.clientname)
                {
                    toAddButton = false;
                }
            }
            if (toAddButton)
            {
                var menuFlyoutItem = new MenuFlyoutItem() { Name = device.clientname, Text = device.clientname };
                menuFlyoutItem.Tag = device.clientaddress;
                menuFlyoutItem.Click += AddMenuFlyoutItem_Click;
                menuFlyout.Items.Add(menuFlyoutItem);
            }
        }
    }
}

This way, the flyout will appear, but will be empty until the asynchronous loading finishes and the items are actually added. Here you are just reading a file, so it should be barely noticeable. Although not as clean as pre-loading the flyout, it should get the job done too.

Upvotes: 1

Related Questions