在资源中使用样式指定网格列和行定义

3

有一个包含以下网格的用户控件:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>
</Grid>

现在我有一个窗口,我想写类似这样的东西:
<Window.Resources>
    <Style TargetType="Grid">
        <Setter Property="RowDefinitions">
            <Value>
                <RowDefinition Height="*"/>
                <RowDefinition/>
            </Value>
        </Setter>
    </Style>
</Window.Resources>

关键部分是当我想将高度从自动更改为*时,它无法编译。如何以合法的方式做到这一点?

通常情况下,我有两种情况。1)第一行应该拉伸,第二行应该固定。2)反之亦然。也许与Grid不同的面板可能更相关?


你的代码无法编译,因为出现了以下错误:“属性设置器'RowDefinitions'无法设置,因为它没有可访问的设置访问器。” 我不确定你具体想做什么,但样式是用来描述视觉对象外观的,而RowDefinition则定义了视觉树本身。 - makc
@mack 问题是如何绕过这个限制? - Ryszard Dżegan
不要在样式中定义RowDefinitions,只需创建另一个网格并更改可见性属性或使用代码后台,但是您应该尝试描述您真正想要实现的内容... - makc
2个回答

8

Grid.RowDefinitionsGrid.ColumnDefinitions不是依赖属性,因此不能通过样式来设置。

你可以在UserControl中创建一个依赖属性FirstRowHeight,并将第一个RowDefinitionHeight绑定到该属性。稍后可以在Style中设置FirstRowHeight属性。

<Grid.RowDefinitions>
    <RowDefinition Height="{Binding FirstRowHeight,
        RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}"/>
    <RowDefinition/>
</Grid.RowDefinitions>

该属性应该是这样的:
public static readonly DependencyProperty FirstRowHeightProperty =
    DependencyProperty.Register(
        "FirstRowHeight", typeof(GridLength), typeof(YourUserControl));

public GridLength FirstRowHeight
{
    get { return (GridLength)GetValue(FirstRowHeightProperty); }
    set { SetValue(FirstRowHeightProperty, value); }
}

编辑:为了支持你在问题结尾提到的简单场景,你也可以有一个IsFirstRowFixed依赖属性,具有一个属性更改回调函数,用于在代码中设置行高度。
<Grid.RowDefinitions>
    <RowDefinition x:Name="row1" Height="*"/>
    <RowDefinition x:Name="row2" Height="Auto"/>
</Grid.RowDefinitions>

该属性:

public static readonly DependencyProperty IsFirstRowFixedProperty =
    DependencyProperty.Register(
        "IsFirstRowFixed", typeof(bool), typeof(UserControl2),
        new PropertyMetadata((o, e) => ((UserControl2)o).IsFirstRowFixedChanged()));

public bool IsFirstRowFixed
{
    get { return (bool)GetValue(IsFirstRowFixedProperty); }
    set { SetValue(IsFirstRowFixedProperty, value); }
}

private void IsFirstRowFixedChanged()
{
    if (IsFirstRowFixed)
    {
        row1.Height = GridLength.Auto;
        row2.Height = new GridLength(1, GridUnitType.Star);
    }
    else
    {
        row1.Height = new GridLength(1, GridUnitType.Star);
        row2.Height = GridLength.Auto;
    }
}

太棒了!相当复杂,但正是我所需要的 :) - Ryszard Dżegan
1
你可以尝试使用DockPanel代替Grid,并在代码后端更改子元素的顺序,以便让最后一个子元素填充剩余空间。但这可能会比现在更加复杂。 - Clemens
那可能是另一个+1的答案。 - Ryszard Dżegan

0

XAML 代码:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
    </Grid.RowDefinitions>
<Grid Grid.Row="1" Style="{StaticResource HeaderHeight}"</>
<Grid Grid.Row="1" Style="{StaticResource FooterHeight}"</>
</>

资源字典中的样式

<Style TargetType="Frame" x:Name="HeaderHeight">
    <Setter Property="Height" Value="700"></Setter>
</Style>
<Style TargetType="Grid" x:Name="FooterHeight">
    <Setter Property="Height" Value="70"></Setter>
</Style>

这并没有回答问题。 - Clemens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接