Xamarin Forms: как установить ширину двух столбцов в сетке динамически с помощью mvvm

Мне нужно произвести расчет в моей модели представления, чтобы показать процентный диапазон между двумя столбцами в сетке.

Я пытаюсь установить свойство строки, чтобы установить значения в модели представления, как показано ниже,

// These two below values/ratio would be calculated dynamically,

public string firstColValue = "3*";
public string secondColValue = "7*";

<Frame CornerRadius="8" Grid.Row="0" HorizontalOptions="FillAndExpand" HeightRequest="8">
<Grid HorizontalOptions="FillAndExpand">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="{Binding firstColValue}">
            </ColumnDefinition>
            <ColumnDefinition Width="{Binding secondColValue}">
            </ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="8">
            </RowDefinition>
        </Grid.RowDefinitions>

            <Label Grid.Row="0" Grid.Column="0" HeightRequest="8" HorizontalOptions="FillAndExpand" BackgroundColor="Lime"></Label>
            <Label Grid.Row="0" Grid.Column="1" HeightRequest="8" HorizontalOptions="FillAndExpand" BackgroundColor="Blue"></Label>

    </Grid>
</Frame>

Это вызывает исключение во время выполнения. Я пытаюсь динамически установить ширину двух столбцов из свойства модели представления.

Пожалуйста, дайте мне знать, как этого добиться.


person Aryan M    schedule 16.01.2019    source источник


Ответы (2)


Эта ошибка возникает из-за того, что вы привязываете строку к ширине, для которой требуется другой объект.

Чтобы исправить это, одно из решений будет использовать Converter, который преобразует ваш тип (тот, который исходит из ViewModel) в тип, ожидаемый для ширины сетки. Подробнее о преобразователях здесь

Нужный вам конвертер будет выглядеть так:

public class IntToGridLengthConverter : IValueConverter
{
    public IntToGridLengthConverter()
    {
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var intValue = System.Convert.ToInt32(value);
        return new GridLength(intValue, GridUnitType.Star);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Тогда в XAML вам просто нужно его использовать.

Добавление нового раздела в XAML и вызов Converter

<ContentPage.Resources>
    <ResourceDictionary>
        <local:IntToGridLengthConverter x:Key="gridLengthConverter" />
    </ResourceDictionary>
</ContentPage.Resources>

Затем с помощью конвертера в привязках

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="{Binding firstColValue, Converter={StaticResource gridLengthConverter}}" />            
    <ColumnDefinition Width="{Binding secondColValue, Converter={StaticResource gridLengthConverter}}"/>            
</Grid.ColumnDefinitions>

Как видите, я использую ключ, который был задан в предыдущей части.

Одно небольшое изменение, которое вам нужно сделать в свойствах ViewModel, - теперь они должны иметь тип int (целое число). Итак, в вашей ViewModel вы должны установить только целую часть значения, которое вы хотите установить, например:

firstColValue = 7; 
secondColValue = 3;

За преобразование этих значений в 7* и 3* соответственно будет отвечать Конвертер.

Использование конвертеров не позволит вам использовать элементы Xamarin.Forms в ваших ViewModels, поскольку они должны быть независимыми. Также этот конвертер можно повторно использовать на любой другой странице, которая вам нужна.

Надеюсь это поможет.-

person pinedax    schedule 16.01.2019
comment
Спасибо за ответ. - person Aryan M; 17.01.2019

Ваша проблема - это объект, который вы пытаетесь связать. Вам нужно использовать GridLength

Например

GridLength test =  new GridLength(3, GridUnitType.Star); // which is "3*"

Просто обновите свою ViewModel, чтобы вернуть значение типа GridLength

person Bruno Caceiro    schedule 16.01.2019