XAML资源字典中的算术运算

Bej*_*asc 5 xaml resourcedictionary ivalueconverter xamarin.forms

我想做的事

我最近一直在探索XAML资源词典.它们非常强大,但是为了减少(甚至进一步)为了适应任何修改而需要进行的更改,我想使用一些基本的算术运算来改变它的HeightRequest属性Entry.

我已经在充分利用OnPlatformOnIdiom不同方面,比如FontSize.

对于iOS平台,我想做HeightRequest一个条目20+(FontSize).将FontSize使用已经设置OnIdiom(它略有增加粒).

在一个完美的世界里,我正在努力做的核心事情可能看起来像
<Setter Property="HeightRequest" Value="{DynamicResource StandardFontSize}+10">

什么"有效"

我有一个工作的解决方案,如果我使用的组合OnIdiomOnPlatform.

<?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>
Run Code Online (Sandbox Code Playgroud)

有了这个'解决方案' - 我需要明确设置值并自己进行计算.虽然这有效,但我希望能够执行基本的算术运算来查找值FontSize,并为其添加一些数字.

我试过的

在我做的另一次尝试中,我找到了一个转换器,并试图使它适应我的用例.虽然没有智能感知或构建/编译错误,但应用程序在打开后立即崩溃.ArithmeticConverter的.cs文件可以在上面的链接中找到.

<?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>
Run Code Online (Sandbox Code Playgroud)

我不完全理解转换器的使用,并且{Binding}在App.xaml中的值内部对我来说也是新的.看看转换器提供的示例,我认为我接近正确,可能只需要朝着正确的方向推进?


是否可以App.xaml单独使用这种基本的算术功能(或使用转换器)?我希望尽可能多地包含这个文件.

我在搜索中发现的其他解决方案已经提到了viewmodel的使用,但这是一个'全局'更改,我希望应用于每个平台/习惯用法的每个条目,所以我看不出这种适应可能如何工作.

谢谢你的时间!

mem*_*nga 4

您的应用程序崩溃的原因之一是 Converter 位于 ResourceDictionary 之外。

解决方案1

仅当分配了 BindingContext 时才应使用绑定,因此您需要在 cs 文件中分配它。

应用程序.cs:

public App()
{
    InitializeComponent();
    BindingContext = new { EntryHeightRequest = 10 };
    MainPage = ...
}
Run Code Online (Sandbox Code Playgroud)

应用程序.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>
Run Code Online (Sandbox Code Playgroud)

算术转换器.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;
}
Run Code Online (Sandbox Code Playgroud)

OnIdiom扩展:

    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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

当心:当我尝试时,BindingContext被传递给ResourceDictionary(但这篇文章与它相矛盾,可能它们被改变了?

解决方案2

与解决方案 1类似,但您可以在 HeightRequest 上使用 OnIdiom 并使用默认值,而不是设置 BindingContext。

<Setter Property="HeightRequest" Value="{OnIdiom Default=10, Converter={StaticResource AScript}, ConverterParameter={StaticResource StandardFontSize}}" />
Run Code Online (Sandbox Code Playgroud)