【问题标题】:Arithmetic Operations inside XAML Resource DictionaryXAML 资源字典中的算术运算
【发布时间】:2018-10-03 02:21:45
【问题描述】:

我想做什么

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

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

对于 iOS 平台,我想将条目 20+(FontSize) 设为 HeightRequestFontSize 已使用 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>

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

我尝试过的

在我进行的另一次尝试中,I've found a converter 并试图使其适应我的用例。虽然没有智能感知或构建/编译错误,但应用程序在打开后立即崩溃。 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>

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


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

我在搜索中找到的其他解决方案提到了视图模型的使用,但这是我想应用于每个平台/习惯用法的每个条目的“全局”更改,所以我可以'不知道这种适应如何工作。

感谢您的宝贵时间!

【问题讨论】:

  • 如果你在你的转换器中放置一个断点,你会明白为什么它会崩溃......一方面,与你链接的例子相反,你没有绑定到任何东西,所以您的转换器中的value 将为空。此外,示例中使用的正则表达式很可能无法满足您的需求。是的,您可以毫无问题地在 App.xaml 中拥有所有这些内容。
  • 这是一个更简洁的解决方案:直接绑定到您的StandardFontSize,然后在转换器本身内部执行您需要的任何数学运算。这样您就不需要ConverterParameter 和正则表达式。
  • 嗯,这是我可以解决的一种方法,但我认为它在我的用例/意图方面有点棘手。我正在有效地尝试设置 CSS 的等效项,并尝试尽可能避开 Binding,因为我正在查看更新样式的现有应用程序(当前不使用资源字典)。许多页面已经对其他类和模型进行了相当复杂的绑定设置。无论如何,我会玩这个概念,看看我能想出什么!感谢您的回复。
  • 我非常期待看到你会想出什么。请在获得解决方案后发布您的解决方案。

标签: xaml xamarin.forms resourcedictionary ivalueconverter


【解决方案1】:

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

解决方案 1

Binding 只能在分配了 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(but this post contradicts it, may be they changed?)

解决方案 2

类似于 解决方案 1,但您可以在 HeightRequest 上使用 OnIdiom 并使用默认值来代替设置 BindingContext。

<Setter Property="HeightRequest" Value="{OnIdiom Default=10, Converter={StaticResource AScript}, ConverterParameter={StaticResource StandardFontSize}}" />

【讨论】:

  • 即使转换器放在资源字典中,它仍然会崩溃,因为还有其他更“严重”的问题,就像我在评论中提到的那样。
猜你喜欢
  • 2016-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多