C# XAML在控件之间划分高度

C# XAML在控件之间划分高度,c#,wpf,xaml,C#,Wpf,Xaml,我有一个按网格分割的窗口(左-中-右),其中的中心控件我希望有多个控件,这些控件需要填充尽可能高的高度,同时在其他控件之间均匀分割 我实现这一点的一种方法是通过这样的网格: <!-- Center --> <Grid Grid.Row="0" Grid.Column="2" Height="Auto"> <Grid.RowDefinitions> <RowDefinition Height="*" />

我有一个按网格分割的窗口(左-中-右),其中的中心控件我希望有多个控件,这些控件需要填充尽可能高的高度,同时在其他控件之间均匀分割

我实现这一点的一种方法是通过这样的网格:

<!-- Center -->
<Grid Grid.Row="0" Grid.Column="2" Height="Auto">
    <Grid.RowDefinitions>
         <RowDefinition Height="*" />
         <RowDefinition Height="*" />
         <RowDefinition Height="*" />

     </Grid.RowDefinitions>

     <WebBrowser Grid.Row="0" Name="browsc" />
     <WebBrowser Grid.Row="1" Name="browsa" />
     <WebBrowser Grid.Row="2" Name="browsb" />
</Grid>

这是有效的,但是我需要动态地添加和删除行,因为中间可能需要删除一行(这就需要重新排序每个控件所依赖的行,我无法想象一个简单的解决方案)。 如果没有比这更好的分割控件的方法,我将如何通过代码(C#)添加和删除行

如果有更好的方法,我该怎么做呢?我所要担心的就是添加和删除控件本身,而不是弄乱行属性


谢谢

这是一个示例,介绍如何以编程方式将新的
行定义添加到
网格
,并将控件设置为特定的
网格行

//following line equal to XAML : <RowDefinition Height="*" />
var newrow = new RowDefinition {Height = new GridLength(1, GridUnitType.Star)};
//add new rowdefinition to grid
myGridName.RowDefinitions.Add(newrow);
//set webbrowser control to newly added row, or any row number you wish
Grid.SetRow(browsx, myGridName.RowDefinitions.Count-1);
//以下行等于XAML:
var newrow=newrowdefinition{Height=newgridlength(1,GridUnitType.Star)};
//将新的行定义添加到网格
myGridName.RowDefinitions.Add(newrow);
//将webbrowser控件设置为新添加的行或任何您想要的行号
SetRow(browsx,myGridName.RowDefinitions.Count-1);

您可以从
myGridName.RowDefinitions
属性访问任何
RowDefinition
,以便稍后删除它。但更好的办法是将
RowDefinition的高度设置为零,而不是将其删除。这样,您就不必重新排列其他控件,例如,将第3行中的控件移动到第2行,因为前一行第2行已被删除。

仍然使用网格的另一种可能性是将高度绑定到转换器,该转换器使用其包含的控件的可见性来决定布局

下面是一个例子:

在XAML文件中:

<Grid Grid.Row="0" Grid.Column="2" Height="Auto" xmlns:local="clr-namespace:WpfApplication2">
    <Grid.Resources>
        <local:RowHeightConverter x:Key="RowHeightConverter" />
    </Grid.Resources>
    <Grid.RowDefinitions>
        <RowDefinition Height="{Binding ElementName=browsc, Path=IsVisible, Converter={StaticResource RowHeightConverter}}" />
        <RowDefinition Height="{Binding ElementName=browsa, Path=IsVisible, Converter={StaticResource RowHeightConverter}}" />
        <RowDefinition Height="{Binding ElementName=browsb, Path=IsVisible, Converter={StaticResource RowHeightConverter}}" />
    </Grid.RowDefinitions>

    <WebBrowser Grid.Row="0" Name="browsc"></WebBrowser>
    <WebBrowser Grid.Row="1" Name="browsa" Visibility="Collapsed"></WebBrowser>
    <WebBrowser Grid.Row="2" Name="browsb"></WebBrowser>
</Grid>

一旦构建了一次代码,就可以在XAML设计器中更改浏览器的“可见性”,并查看布局中反映的更改。

这似乎是一个很好的例子:


UniformGrid
确保所有项目的宽度和高度都相同。在本例中,您只希望约束高度,但由于只有一列,所有项目的宽度都必须相同,因此这是可以的


我们不需要设置行,只需在
UniformGrid
上设置
Columns=“1”
,它就会自动在新行上排列每个项目。如果您添加或删除项目,或在
可见
折叠
之间切换项目的
可见性
,所有大小都将调整以适应空间。

您需要多大的动态性?如果您只需要选择性地隐藏中间行,您可以将其内容的可见性设置为
折叠
。如果你需要支持任意数量的行,那么如果我设置中间行的可见性崩溃,它将不工作,它只是在中间形成了一个不可见的间隔,因为那里仍然应该有一行。但我最终希望支持任意数量的行。范围从2到5或6不等,这取决于用户选择的数量和屏幕大小(最终他们甚至无法查看每个屏幕中显示的数据)。为什么不使用
StackPanel
,当您添加或删除UI元素时,它会自动调整?控件没有垂直拉伸以均匀填充。至少不是以我尝试的方式,再一次,我的XAML体验是非常具有介绍性的。好吧,我认为以这种方式添加一个网格行不会太糟糕。删除一行怎么样?上面已经解释过,
myGridName.RowDefinitions[rownumber]
将为您提供一个RowDefinition对象。您可以删除该对象以删除行定义,或者根据我的喜好将其高度设置为0。哦,我的错。这就是我只扫描代码片段得到的结果。我非常喜欢将高度设置为0的想法。这似乎奏效了。在我选择被接受的答案之前,我将等待是否有人提出另一个解决方案:)完美!我知道必须有一个简单的方法来做到这一点。谢谢你让我注意到这个控件!
public class RowHeightConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var isVisible = value as bool?;
        if (isVisible.HasValue && isVisible.Value)
            return new GridLength(1, GridUnitType.Star);
        else
            return new GridLength(0);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
<UniformGrid Grid.Row="0" Grid.Column="2" Columns="1">
    <WebBrowser Name="browsc" />
    <WebBrowser Name="browsa" />
    <WebBrowser Name="browsb" />
</UniformGrid>