17
votes

For UWP I need a different size for the width of a column in a Grid. Additionally, the value should be different on tablet and on smartphone.

The following code crashes the app

<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>

with

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

The code is in a ViewCell. So I can't use an additional ResourceDictionary and also OnSizeAllocated() is not available in the code behind file.

Is it possible to use OnIdiom and OnPlatform together?

5

5 Answers

27
votes

OnIdiom, just like OnPlatform is an object you have to declare. In your case, you're setting OnIdiom.Phone property to an object that doesn't have those.

Your Xaml should look more like:

<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>
15
votes

Much nicer syntax as of Xamarin.Forms v3.2 (via new built-in XAML extensions):

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

Xamarin.Forms Xaml Example:

<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>
3
votes

Here is the solution to mix OnIdiom and OnPlatform in xaml. For Example, there are variations in stack layout padding then we can do this as follows -

   <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>
0
votes

One option which works in code is to use

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

to overwrite the existing Xaml definition. innerGrid is the name of the Grid used in the Xaml.