【问题标题】:Setting Grid RowDefinitions/ColumnDefinitions properties in a style在样式中设置 Grid RowDefinitions/ColumnDefinitions 属性
【发布时间】:2018-01-22 15:50:28
【问题描述】:

假设您有 2 个或更多共享相同结构的网格(行/列数和属性相等)。

是否可以创建Style并设置RowDefinitions/ColumnDefinitions

我已经试过了。但是当应用程序尝试解析 xaml 时出现此异常:

Xamarin.Forms.Xaml.XamlParseException:位置 14:9。属性值为 null 或不是 IEnumerable

我的源代码:

<StackLayout>
    <StackLayout.Resources>
        <ResourceDictionary>
            <Style TargetType="Grid">
                <Setter Property="RowDefinitions">
                    <Setter.Value>
                        <RowDefinition />
                        <RowDefinition />
                    </Setter.Value>
                </Setter>
            </Style>
        </ResourceDictionary>
    </StackLayout.Resources>

    <Grid>
        <Label Grid.Row="0" Text="(Grid #1) Row #1" />
        <Label Grid.Row="1" Text="(Grid #1) Row #2" />
    </Grid>

    <Grid>
        <Label Grid.Row="0" Text="(Grid #2) Row #1" />
        <Label Grid.Row="1" Text="(Grid #2) Row #2" />
    </Grid>

    <Grid>
        <Label Grid.Row="0" Text="(Grid #3) Row #1" />
        <Label Grid.Row="1" Text="(Grid #3) Row #2" />
    </Grid>
</StackLayout>
异常中的

14:9位置指的是第一个&lt;RowDefinition /&gt;标签。

【问题讨论】:

    标签: xaml xamarin.forms xamarin.forms-styles


    【解决方案1】:

    你不能,我认为你不应该。

    定义网格不是关于样式,而是关于布局。

    从 Xamarin.Forms 版本 3 开始,将引入更多类似 CSS 的样式功能。也许您将能够像在 HTML/CSS 中那样设置网格的样式。但对于将实施什么以及如何实施,我们知之甚少。

    【讨论】:

    • 您好 Gerald Versluis,感谢您的快速回复。但如果可能的话,那就太好了。因为就像一种方法一样,您可以在一个地方更改代码,它会在多个地方生效。这是我的意见。也许创建一个自定义控件可以解决这个问题。
    【解决方案2】:

    您不能在样式中定义RowDefinitionColumnDefinition,但可以将它们创建为可重用资源。我想这就是你要找的。像这样定义 ColumnDefinitionCollectionRowDefinitionCollection 可以让您在许多网格中重复使用它们以创建一致的外观。

    <ResourceDictionary>
        <ColumnDefinitionCollection
            x:Key="MyColumnDefinitionCollection">
            <ColumnDefinition
                Width="50" />
            <ColumnDefinition
                Width="100" />
            <ColumnDefinition
                Width="150" />
        </ColumnDefinitionCollection>
        <RowDefinitionCollection
            x:Key="MyRowDefinitionCollection">
            <RowDefinition
                Height="50" />
            <RowDefinition
                Height="50" />
            <RowDefinition
                Height="100" />
            <RowDefinition
                Height="100" />
        </RowDefinitionCollection>
    </ResourceDictionary>
    
    <Grid 
        ColumnDefinitions="{StaticResource MyColumnDefinitionCollection}"
        RowDefinitions="{StaticResource MyRowDefinitionCollection}">
    </Grid>
    

    【讨论】:

    • 来自@jf 的非常好的建议 或者,您可以创建一个从 Grid 派生的类,设置所有内容,然后在任何地方使用它。好吧,我也会把它作为答案:-)
    • 很好的答案!我正在努力在 Android 和 Windows 中制作宽度略有不同的两列,这个答案给了我解决方案。刚刚用 定义了资源并且工作得很好!
    • 似乎对我不起作用,我收到错误消息:The type "ColumnDefinitionCollection" does not include any accessible constructorsThe property "ColumnDefinitions" does not have an accessible setter.
    • @Alfie,我又试了一次,它似乎对我来说仍然很好。我建议创建另一个问题,其中包含有关如何重现问题的步骤。
    【解决方案3】:

    您可以创建一个从 Grid 派生的类

    public class MyGrid : Grid
    

    设置它,然后在 xamls 中随处使用

    <local:MyGrid> 
    

    正如j.f所说,它被称为用户控制

    【讨论】:

      【解决方案4】:

      感谢@j.f.,我找到了解决方案。我将他的想法与我的想法结合起来,结果如下:

      诀窍是将声明添加到单独的资源中并在样式中引用它。

      <StackLayout>
          <StackLayout.Resources>
              <ResourceDictionary>
                  <RowDefinitionCollection x:Key="MyRowDefinitionCollection">
                      <RowDefinition />
                      <RowDefinition />
                  </RowDefinitionCollection>
      
                  <Style TargetType="Grid">
                      <Setter Property="RowDefinitions" Value="{StaticResource MyRowDefinitionCollection}" />
                  </Style>
              </ResourceDictionary>
          </StackLayout.Resources>
      
          <Grid>
              <Label Grid.Row="0" Text="(Grid #1) Row #1" />
              <Label Grid.Row="1" Text="(Grid #1) Row #2" />
          </Grid>
      
          <Grid>
              <Label Grid.Row="0" Text="(Grid #2) Row #1" />
              <Label Grid.Row="1" Text="(Grid #2) Row #2" />
          </Grid>
      
          <Grid>
              <Label Grid.Row="0" Text="(Grid #3) Row #1" />
              <Label Grid.Row="1" Text="(Grid #3) Row #2" />
          </Grid>
      </StackLayout>
      

      【讨论】:

        【解决方案5】:

        我找到了一个更好更简单的解决方案。答案只是在 RowDefinition 标签周围添加 RowDefinitionCollection 标签。

        像这样:

        <StackLayout>
            <StackLayout.Resources>
                <ResourceDictionary>
                    <Style TargetType="Grid">
                        <Setter Property="RowDefinitions">
                            <Setter.Value>
                                <RowDefinitionCollection>
                                    <RowDefinition />
                                    <RowDefinition />
                                </RowDefinitionCollection>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </ResourceDictionary>
            </StackLayout.Resources>
        
            <Grid>
                <Label Grid.Row="0" Text="(Grid #1) Row #1" />
                <Label Grid.Row="1" Text="(Grid #1) Row #2" />
            </Grid>
        
            <Grid>
                <Label Grid.Row="0" Text="(Grid #2) Row #1" />
                <Label Grid.Row="1" Text="(Grid #2) Row #2" />
            </Grid>
        
            <Grid>
                <Label Grid.Row="0" Text="(Grid #3) Row #1" />
                <Label Grid.Row="1" Text="(Grid #3) Row #2" />
            </Grid>
        </StackLayout>
        

        【讨论】:

        • 我认为这不适合 OP,因为它不能跨不同的 XAML 文件重用。不过我可能是错的。
        • 我从未听说过 RoweDefinition 集合
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-17
        • 1970-01-01
        • 1970-01-01
        • 2023-04-02
        • 2011-07-31
        • 1970-01-01
        • 2021-02-03
        相关资源
        最近更新 更多