XAML 资源字典中的算术运算
Arithmetic Operations inside XAML Resource Dictionary
我想做什么
我最近一直在探索 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>
有了这个 'solution' - 我需要明确设置值并自己进行计算。虽然这可行,但我希望能够执行基本算术运算来找到 FontSize
的值,并向其添加一些数字。
我试过的
在我所做的另一次尝试中,I've found a converter 并尝试使其适应我的用例。虽然没有智能感知或 build/compile 错误,但应用程序在打开后立即崩溃。 ArithmeticConverter 的 .cs 文件可以在上面的 link 中找到。
<?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
中执行这种基本的算术函数?我希望尽可能多地包含此文件。
我在搜索中找到的其他解决方案提到了视图模型的使用,但这是一个 'global' 更改,我想应用到每个 每个 个条目platform/idiom,所以我看不出这种改编是如何工作的。
感谢您的宝贵时间!
您的应用程序崩溃的原因之一是 Converter 在 ResourceDictionary 之外。
解决方案 1
只有在分配了 BindingContext 时才应使用 Binding,因此您需要在 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}}" />
我想做什么
我最近一直在探索 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>
有了这个 'solution' - 我需要明确设置值并自己进行计算。虽然这可行,但我希望能够执行基本算术运算来找到 FontSize
的值,并向其添加一些数字。
我试过的
在我所做的另一次尝试中,I've found a converter 并尝试使其适应我的用例。虽然没有智能感知或 build/compile 错误,但应用程序在打开后立即崩溃。 ArithmeticConverter 的 .cs 文件可以在上面的 link 中找到。
<?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
中执行这种基本的算术函数?我希望尽可能多地包含此文件。
我在搜索中找到的其他解决方案提到了视图模型的使用,但这是一个 'global' 更改,我想应用到每个 每个 个条目platform/idiom,所以我看不出这种改编是如何工作的。
感谢您的宝贵时间!
您的应用程序崩溃的原因之一是 Converter 在 ResourceDictionary 之外。
解决方案 1
只有在分配了 BindingContext 时才应使用 Binding,因此您需要在 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}}" />