是否可以在 XAML (Xamarin.Forms) 中混合使用 OnIdiom 和 OnPlatform?

Is it possible to mix OnIdiom and OnPlatform in XAML (Xamarin.Forms)?

对于 UWP,我需要 Grid 中列宽的不同大小。此外,平板电脑和智能手机上的值应该不同。

以下代码会使应用程序崩溃

<ColumnDefinition>
    <ColumnDefinition.Width>
        <OnIdiom.Phone>
            <OnPlatform x:TypeArguments="GridLength" iOS="*" Android="*" WinPhone="100" />
        </OnIdiom.Phone>
        <OnIdiom.Tablet>
            <OnPlatform x:TypeArguments="GridLength" iOS="*" Android="*" WinPhone="200" />
        </OnIdiom.Tablet>
    </ColumnDefinition.Width>
</ColumnDefinition>

Type OnIdiom.Phone not found in xmlns http://xamarin.com/schemas/2014/forms

代码在 ViewCell 中。所以我不能使用额外的 ResourceDictionary 并且 OnSizeAllocated() 在代码隐藏文件中不可用。

可以同时使用OnIdiomOnPlatform吗?

一个在代码中有效的选项是使用

if(Device.OS == TargetPlatform.Windows && Device.Idiom == TargetIdiom.Phone)
    this.innerGrid.ColumnDefinitions.First().Width = new GridLength(100);

覆盖现有的 Xaml 定义。 innerGrid 是在 Xaml 中使用的 Grid 的名称。

Xamarin.Forms Xaml 示例:

<OnPlatform x:TypeArguments="View">
    <OnPlatform.Android>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition>
                    <ColumnDefinition.Width>
                        <OnIdiom x:TypeArguments="GridLength" Tablet="100" Phone="50" />
                    </ColumnDefinition.Width>
                </ColumnDefinition>
                <ColumnDefinition>
                    <ColumnDefinition.Width>
                        <OnIdiom x:TypeArguments="GridLength" Tablet="100" Phone="50" />
                    </ColumnDefinition.Width>
                </ColumnDefinition>
            </Grid.ColumnDefinitions>
        </Grid>
    </OnPlatform.Android>
    <OnPlatform.iOS>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition>
                    <ColumnDefinition.Width>
                        <OnIdiom x:TypeArguments="GridLength" Tablet="100" Phone="50" />
                    </ColumnDefinition.Width>
                </ColumnDefinition>
                <ColumnDefinition>
                    <ColumnDefinition.Width>
                        <OnIdiom x:TypeArguments="GridLength" Tablet="100" Phone="50" />
                    </ColumnDefinition.Width>
                </ColumnDefinition>
            </Grid.ColumnDefinitions>
        </Grid>
    </OnPlatform.iOS>
</OnPlatform>

OnIdiom,就像OnPlatform是一个你必须声明的对象。在您的情况下,您将 OnIdiom.Phone 属性 设置为一个没有这些对象的对象。

您的 Xaml 应该看起来更像:

<ColumnDefinition>
  <ColumnDefinition.Width>
    <OnIdiom x:TypeArguments="GridLength">
      <OnIdiom.Phone>
        <OnPlatform x:TypeArguments="GridLength" iOS="*" Android="*" WinPhone="100" />
      </OnIdiom.Phone>
      <OnIdiom.Tablet>
        <OnPlatform x:TypeArguments="GridLength" iOS="*" Android="*" WinPhone="200" />
      </OnIdiom.Tablet>
    </OnIdiom>
  </ColumnDefinition.Width>
</ColumnDefinition>

从 Xamarin.Forms v3.2 开始更好的语法(通过新的内置 XAML 扩展):

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="{OnIdiom 
        Phone= {OnPlatform iOS=*, Android=*, UWP=100 },
        Tablet= {OnPlatform iOS=*, Android=*, UWP=200 }}">
    </ColumnDefinition>
</Grid.ColumnDefinitions>

这里是在xaml中混合OnIdiom和OnPlatform的解决方案。例如,堆栈布局填充有变化,那么我们可以按如下方式进行 -

   <StackLayout.Padding>
                        <OnIdiom x:TypeArguments="Thickness">
                        <OnIdiom.Phone>
                            <OnPlatform x:TypeArguments="Thickness" iOS="0,40,0,0" Android="15,0" WinPhone="15,0" />
                        </OnIdiom.Phone>
                        <OnIdiom.Tablet>
                            <OnPlatform x:TypeArguments="Thickness" iOS="15,0" Android="15,0" WinPhone="15,0" />
                        </OnIdiom.Tablet>
                      </OnIdiom>

</StackLayout.Padding>