Арифметические операции внутри словаря ресурсов XAML - PullRequest
0 голосов
/ 03 октября 2018

Что я хочу сделать

Я недавно изучал словари ресурсов XAML.Они очень мощные, но для того, чтобы сократить (даже дальше) изменения, которые необходимо внести, чтобы приспособиться к любым изменениям, я хотел бы использовать некоторые основные арифметические операции для изменения свойства HeightRequest Entry.

Я уже хорошо использую OnPlatform и OnIdiom для различных аспектов, например FontSize.

Для платформы iOS я хотел бы сделать HeightRequest записи 20+(FontSize).FontSize уже установлен с помощью OnIdiom (он немного увеличен для планшетов).

В идеальном мире основная вещь, которую я пытаюсь сделать, может выглядеть примерно так:
<Setter Property="HeightRequest" Value="{DynamicResource StandardFontSize}+10">

Что "работает"

У меня есть рабочее решение, если я использую комбинацию OnIdiom и OnPlatform.

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamarinDesigner.App"
             xmlns:local="clr-namespace:XamarinDesigner"
             >
    <Application.Resources>
        <ResourceDictionary>
            <OnIdiom x:Key="StandardFontSize" x:TypeArguments="x:Double"  Tablet="22" Phone="18"/>
            <Style x:Key="MyEntry" TargetType="Entry">
                <Setter Property="FontSize" Value="{DynamicResource StandardFontSize}"/>
                <Setter Property="HeightRequest">
                    <Setter.Value>
                        <OnIdiom x:TypeArguments="x:Double">
                            <OnIdiom.Phone>
                                <OnPlatform x:TypeArguments="x:Double" iOS="30"/>
                            </OnIdiom.Phone>
                            <OnIdiom.Tablet>
                                <OnPlatform x:TypeArguments="x:Double" iOS="40"/>
                            </OnIdiom.Tablet>
                        </OnIdiom>
                    </Setter.Value>
                </Setter>
                <Setter Property="VerticalOptions" Value="Center"/>
            </Style>
        </ResourceDictionary>
    </Application.Resources>
</Application>

С этим «решением» - мне нужно явно установить значение и выполнить вычисления самостоятельно.Хотя это работает, я хотел бы иметь возможность выполнить основную арифметическую операцию, чтобы найти значение FontSize и добавить к нему некоторое число.

Что я пробовал

В другой попытке, которую я предпринял, Я нашел конвертер и попытался адаптировать его к своему варианту использования.Хотя нет ошибок intellisense или build / compile, приложение вылетает сразу после открытия.Файл .cs для ArithmeticConverter можно найти по ссылке выше.

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamarinDesigner.App"
             xmlns:local="clr-namespace:XamarinDesigner"
             >
    <Application.Resources>
        <local:ArithmeticConverter x:Key="AScript"/>

        <ResourceDictionary>
            <OnIdiom x:Key="StandardFontSize" x:TypeArguments="x:Double"  Tablet="22" Phone="18"/>

            <Style x:Key="MyEntry" TargetType="Entry">
                <Setter Property="FontSize" Value="{DynamicResource StandardFontSize}"/>
                <Setter Property="HeightRequest" Value="{Binding Converter={StaticResource AScript},ConverterParameter=Int32.Parse(20+{DynamicResource StandardFontSize}}"/>
                <Setter Property="VerticalOptions" Value="Center"/>
            </Style>

        </ResourceDictionary>
    </Application.Resources>
</Application>

Я не совсем понимаю использование конвертеров, и {Binding} внутри значения в App.xaml также является чем-то новым для меня.Глядя на пример, поставляемый с конвертером, я думаю, что я близок к правильности и, возможно, просто нужно нажать в правильном направлении?


Можно ли это сделатьэто основной вид арифметической функции только в App.xaml (или с использованием преобразователя)?Я надеюсь содержать как можно больше в этом файле.

В других решениях, которые я нашел в своем поиске, упоминалось использование модели представления, но это «глобальное» изменение, которое я хочу применить к каждой записи для платформы / идиомы, поэтомуЯ не понимаю, как эта адаптация может работать.

Спасибо за ваше время!

1 Ответ

0 голосов
/ 15 октября 2018

Одна из причин сбоя вашего приложения в том, что Converter находится за пределами ResourceDictionary.

Решение 1

Привязка должна использоваться только в том случае, если назначен BindingContextследовательно, вам нужно назначить его в файле cs.

App.cs:

public App()
{
    InitializeComponent();
    BindingContext = new { EntryHeightRequest = 10 };
    MainPage = ...
}

App.xaml:

<ResourceDictionary>
    <local:ArithmeticConverter x:Key="AScript"/>
    <OnIdiom x:Key="StandardFontSize" x:TypeArguments="x:Double"  Tablet="22" Phone="18"/>
    <Style x:Key="MyEntry" TargetType="Entry">
        <Setter Property="FontSize" Value="{DynamicResource StandardFontSize}" /> 
        <Setter Property="HeightRequest" Value="{Binding EntryHeightRequest, Converter={StaticResource AScript},ConverterParameter="{StaticResource StandardFontSize}"/>
        <Setter Property="VerticalOptions" Value="Center"/>
    </Style>
</ResourceDictionary>

ArithmeticConverter.cs:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    if(value is int constant && parameter is OnIdiom<double> dynamicSize)
        return constant + dynamicSize.GetValue();
    return -1;
}

OnIdiomExtension:

    public static T GetValue<T>(this OnIdiom<T> idiom)
    {
        switch(Device.Idiom)
        {
            case TargetIdiom.Phone:
                return idiom.Phone;

            case TargetIdiom.Desktop:
                return idiom.Desktop;

            case TargetIdiom.Tablet:
                return idiom.Tablet;

            case TargetIdiom.TV:
                return idiom.TV;

            case TargetIdiom.Watch:
                return idiom.Watch;

            default:
                throw new NotSupportedException();
        }
    }

Осторожно : Когда я пытался, BindingContext передается ResourceDictionary (, но этот пост противоречит этому, возможно, они изменились? )

Решение 2

Аналогично Решение 1 , но вместо установки BindingContext вы можете использовать OnIdiom для HeightRequest со значением по умолчанию.

<Setter Property="HeightRequest" Value="{OnIdiom Default=10, Converter={StaticResource AScript}, ConverterParameter={StaticResource StandardFontSize}}" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...