Как я могу привязаться к ширине определения столбца сетки в C# - PullRequest
6 голосов
/ 19 июня 2020

У меня есть привязка:

public static readonly BindableProperty 
   EntryWidthProperty = BindableProperty.Create(nameof(EntryWidth),
   typeof(int),
   typeof(SingleEntryGrid), 150, BindingMode.TwoWay);
public int EntryWidth { 
   get => (int)GetValue(EntryWidthProperty); 
   set => SetValue(EntryWidthProperty, value); 
}

и этот C# код:

var column3 = new ColumnDefinition()
{
   Width = new GridLength(???, GridUnitType.Absolute)
};

Обратите внимание, что GridLength - это структура:

https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.gridlength?view=xamarin-forms

enter image description here

Does anyone know how I can bind to the value marked with ???

For more explanation here's what I am trying to do:

введите описание изображения здесь

Я хотел бы иметь возможность устанавливать ширину рамок поля ввода. В этом примере все они одинаковой ширины.

1 Ответ

5 голосов
/ 22 июня 2020

Вы не можете этого сделать. Как вы сказали, GridLength является структурой, но, возможно, более важным, чем это, является то, что Value , которое вы устанавливаете, является просто свойством publi c с геттером (это не даже BindableProperty ). Это означает, что вы можете установить его только с помощью метода, которым в данном случае является сам GridLength ctor. Вы можете проверить код GridLength здесь .

Вы можете сделать одно из двух: либо оставьте всю необходимую ширину равной Auto, либо создайте подкласс Grid класс.

Если вы решите использовать go для первого подхода, вам не придется писать дополнительный код. Согласно Строкам и столбцам docs:

Auto - высота строки или ширина столбца автоматически изменяются в зависимости от содержимого ячейки (Авто в XAML).

На первый взгляд, это должно сработать, так как все значения ширины будут принимать максимальную ширину дочерних элементов (в данном случае это будет 150). К сожалению, это добавляет некоторые накладные расходы на рендеринг Grid, и в любом случае это не мало. Если вы посмотрите немного вниз в документации, вы увидите красное предупреждение о том, что вам следует:

Постарайтесь убедиться, что как можно меньше строк и столбцов имеют размер Auto. Каждая строка или столбец с автоматическим изменением размера заставляет механизм макета выполнять дополнительные вычисления макета. Вместо этого по возможности используйте строки и столбцы фиксированного размера. В качестве альтернативы установите для строк и столбцов пропорциональное пространство с помощью значения перечисления GridUnitType.Star.

Это также можно снова увидеть в Оптимизация производительности макета , что я настоятельно Предлагаю вам прочитать, если вы еще этого не сделали.

При этом вы можете go со вторым подходом. Идея заключается в том, чтобы иметь связываемое свойство внутри вашего нового класса, и после установки этого свойства вы обновите свое свойство ColumnDefinition Width. К сожалению, это приходится делать «вручную». Вот пример вашего свойства (я изменил его тип на double, чтобы он совпадал со свойством Width столбца):

public partial class MainPage
{
    private ColumnDefinition column3;
    
    public static readonly BindableProperty EntryWidthProperty = BindableProperty.Create(nameof(EntryWidth), typeof(double),
        typeof(SingleEntryGrid), (double) 150, BindingMode.TwoWay);
    public double EntryWidth
    {
        get => (double) GetValue(EntryWidthProperty);
        set
        {
            SetValue(EntryWidthProperty, value);
            if (column3 != null)
            {
                column3.Width = value;
            }
        }
    }
    public MainPage()
    {
        InitializeComponent();
    
        var grid = new SingleEntryGrid
        {
            ColumnDefinitions = new ColumnDefinitionCollection()
        };
        // TODO: Other columns
        column3 = new ColumnDefinition
        {
            // The default value for EntryWidth
            Width = new GridLength(150, GridUnitType.Absolute)
        };
        grid.ColumnDefinitions.Add(column3);
        // The rest of your code
        
        Content = grid;
    }
}

Как вы можете видеть в коде, третий столбец изначально устанавливается на Absolute ширину 150 (значение по умолчанию для EntryWidth). После некоторого изменения значения свойства EntryWidth сеттер автоматически изменит третий столбец.

Конечно, это не самое элегантное решение, поскольку оно всегда обновляет только третий столбец, но вы можно продолжить отсюда. Поскольку я не знаю точно, в чем дело и против чего он будет использоваться, я не могу сказать, что является лучшим выбором - либо создать больше свойств для каждого столбца, либо создать их список с ключом-значением ( может быть даже отдельным классом), привязанным к ним - таким образом, вы можете настроить его динамически для каждого столбца.

PS И все же, если вы знаете свою ширину с самого начала или у вас есть только 1 столбец, который требует быть Auto, go с традиционным подходом. Постарайтесь не усложнять все и соответствующим образом установите определения столбцов.

Изменить: в соответствии с обновленным вопросом мы должны использовать другой подход. Из изображения я не могу полностью понять, что такое общий шаблон, но у нас есть 2 варианта:

  1. Чтобы все входы были везде одинаковой ширины;
  2. Или иметь разную ширину.

Однако, что бы мы ни выбрали, столбец будет иметь одинаковую ширину для всех представлений. Что я могу предложить в этом случае, так это сделать так, чтобы все входы были одинаковой ширины (установите их HorizontalOptions на StartAndExpand или FillAndExpand). И вместо того, чтобы явно указывать их ширину, вы можете попытаться установить ширину столбца (в зависимости от конфигурации других столбцов):

  1. Если у вас нет других столбцов, установленных на Star (*) или вы не хотите, чтобы столбец был пропорционален другим звездам - ​​установите его ширину на Star. Таким образом, столбец примет все, что осталось.
  2. Или установите ширину столбца равной Absolute значению.

Вы не должны пытаться динамически изменять столбец - это не будет хорошим UX, и вам также придется добавлять проверки, когда следует останавливаться.

Подводя итог, либо установите третий столбец (содержащий записи) до Star или Absolute. Если один из ваших других столбцов установлен на Auto, а другой имеет ширину Absolute, вы можете легко установить третий столбец на Star, который займет столько же ширины, сколько осталось). Absolute следует использовать, если вы хотите каждый раз брать "столько" ширины (используйте его с самой большой записью / символами, которые вы хотите видеть).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...