Эмулятор Android Xamarin использует сетку внутри scrollview, рисуется только первая страница сетки

#xamarin #xamarin.forms

Вопрос:

Я разрабатываю приложение Xamarin Forms в Visual Studio 2019 с использованием стандартного эмулятора Android. XAML содержит представление прокрутки, содержащее сетку. Сетка состоит всего из двух столбцов. У меня есть обработчик для события OnStart, который подключается к базе данных, получает ответ, содержащий 64 объекта, добавляет две метки в сетку для каждого объекта и заполняет метки. Цвет фона прокрутки установлен на желтый. Когда я отлаживаю приложение с помощью эмулятора, начальный экран отображается правильно. Но когда я прокручиваю вниз, сетка не заполняется. Фон по-прежнему желтый, показывая, что вид прокрутки имеет правильный размер (или, по крайней мере, достаточно большой, чтобы вместить больше меток). Что я делаю не так?

Когда я помещаю точку останова в нижней части второго цикла for после добавления меток, я вижу, что у меня есть все объекты меток, которые я ожидаю, и у них заданы свойства текста, как я и ожидал.

Вот XAML:

 <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CapsBases.MainPage">

    <ScrollView BackgroundColor="Yellow"
                VerticalOptions="FillAndExpand">
        <Grid Margin="10"
              x:Name="BasesGrid">
            <!-- two columns:  base ID and status -->
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="60" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>

        </Grid>
    </ScrollView>
</ContentPage>
 

Обработчик событий вызывает функцию с именем ShowBases() в файле MainPage.xaml.cs. Вот он:

 public async void ShowBases()
{
    string url = "http://10.0.2.2:5000/caps/bases";
    //HttpClient client = new HttpClient();
    //string info = await client.GetStringAsync(url);
    //// await DisplayAlert("Coil Count", message, "Close");
    //// The base ID and string will be returned in a single string with a space separating them.
    //string[] pieces = info.Split(' ');
    //BaseID.Text = pieces[0];
    //BaseStatus.Text = pieces[1];
    using (HttpClient client = new HttpClient())
    {
        HttpResponseMessage response = await client.GetAsync(url);
        if (response.IsSuccessStatusCode)
        {
            string data = await response.Content.ReadAsStringAsync();
            //IEnumerable<Base> baseList = JsonConvert.DeserializeObject<IEnumerable<Base>>(data);
            List<Base> baseList = JsonConvert.DeserializeObject<List<Base>>(data).OrderBy(b =>b.BaseName).ToList();
            //BaseID.Text = theBase.BaseName;
            //BaseStatus.Text = theBase.Status;
            string message = $"Retrieved {baseList.Count()} bases.";
            await DisplayAlert("Result", message, "Close");

            Grid theGrid = BasesGrid;
            var rowDefinitions = theGrid.RowDefinitions;
            for (int i = 0; i < baseList.Count(); i  )
            {
                RowDefinition rowDef = new RowDefinition { Height = 20 };
                rowDefinitions.Add(rowDef);
            }

            await DisplayAlert("Row count", $"The grid has {BasesGrid.RowDefinitions.Count()} rows.", "Close");

            // We have the grid with all the rows we need.  Now we have to create a label for each grid cell.

            try
            {
                for (int i = 0; i < baseList.Count(); i  )
                {
                    BasesGrid.Children.Add
                    (
                        new Label
                        {
                            Text = baseList[i].BaseName,
                            HorizontalOptions = LayoutOptions.Start
                        },
                        0, i
                    );
                    BasesGrid.Children.Add
                    (
                        new Label
                        {
                            Text = baseList[i].Status,
                            HorizontalOptions = LayoutOptions.Start
                        },
                        1, i
                    );
                }
            }
            catch (Exception ex)
            {
                await DisplayAlert("Error", $"Failed to add row data: {ex.Message}", "Close");

            }
        }
        else
        {
            await DisplayAlert("Get Coils failure",
                                $"Failed to retrieve coils; status code: {response.StatusCode}",
                                "Close");
        }
    }

}
 

}

Комментарии:

1. Об этой проблеме уже сообщалось. Вы могли бы попробовать то, что предложил Федорсулаев. github.com/xamarin/Xamarin. Формы/вопросы/4180

2. Я не вижу, чтобы решение Федора отличалось от моего. Он отвечает требованию для фиксированной части и прокручиваемой части. Его прокручиваемая часть состоит из представления прокрутки, содержащего сетку, такую же, как у меня.

Ответ №1:

Окружите сетку в виде штабеля вертикальной ориентации. Сетка не расширяется внутри представления прокрутки.

Комментарии:

1. Спасибо. Я попробую это сделать. Какие вертикальные опции я должен использовать для стекирования, просмотра прокрутки и сетки?

2. Это сработало! Мне не нужны были какие-либо атрибуты в StackLayout или ScrollView, а в сетке просто были заданы поля и x:Имя. Большое спасибо!

3. Пожалуйста. Вам не нужно устанавливать вертикальные параметры, потому что StackLayout со значением по умолчанию Fill будет расширяться по вертикали , чтобы соответствовать своим дочерним элементам. Подумайте о том, чтобы отметить мой ответ как решение, которое поможет другим в будущем.

4. Спасибо за напоминание о принятии вашего ответа. Это было сделано.