xaml 中网格元素的条件边距

Conditional margining for a grid elements in xaml

我有一个 2 行 4 列的网格,其宽度和高度如下指定。第二行在 col=1 中只有一个控件,并且该控件可能存在也可能不存在(由于某种逻辑)。

          <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions></Grid>

当控件不存在时:

由于第二行的高度是“自动”,当我无法控制时,我将只有一行。在那种情况下,我需要相对于网格底部有特定的边距。 因此,第 0 行的边距控制 = "0,0,0,14"

存在控件时:

存在控件时,我有两行,我需要在两行元素之间留出 6px 的边距,第二行边距应为 14 w.r.t 网格底部。 因此,第 0 行控件的边距 = "0,0,0,6" 和第 1 行控件的边距 = "0,0,0 ,14

我如何根据第二行的存在来实现这些不同的边距值。请帮忙。提前致谢。 参考img:

根据您的要求,您可以使用 MarginConverter 根据第 1 行控件是否存在来设置第 0 行控件边距。

例如

public class MarginConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        Thickness newMargin;
        var visibility = (Visibility)value;
        switch (visibility)
        {
            case Visibility.Visible:
                newMargin = new Thickness(0, 0, 0, 6);

                break;
            case Visibility.Collapsed:
                newMargin = new Thickness(0, 0, 0, 14);
                break;
            default:
                break;
        }
        return newMargin;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

用法

 <Page.Resources>
     <local:MarginConverter x:Key="Conveter" />
 </Page.Resources>
 <Grid>
     <Grid.RowDefinitions>
         <RowDefinition Height="*" />
         <RowDefinition Height="Auto" />
     </Grid.RowDefinitions>
     <Grid.ColumnDefinitions>
         <ColumnDefinition Width="Auto" />
         <ColumnDefinition Width="*" />
         <ColumnDefinition Width="Auto" />
         <ColumnDefinition Width="*" />
     </Grid.ColumnDefinitions>
     <Rectangle
         Grid.Row="0"
         Grid.Column="1"
         Margin="{Binding ElementName=Row1Control, Path=Visibility, Converter={StaticResource Conveter}}"
         Fill="Red" />
     <Rectangle
         x:Name="Row1Control"
         Grid.Row="1"
         Grid.Column="1"
         Height="80"
         Margin="0,0,0,14"
         Fill="Black"
         Visibility="Visible" />
 </Grid>

更新

But in my case, Row1Control is dynamically set in the backend.

您可以检测到 RootGrid LayoutUpdated 事件,如果您添加控件,它将被调用,然后在以下方法中重新设置 MarginProperty。

private int oldCount;
private void RootGrid_LayoutUpdated(object sender, object e)
{
   
    if(RootGrid.Children.Count > oldCount)
    {
        if (RootGrid.Children.Any(p => p.GetValue(NameProperty).ToString() == "Row1Control"))
        {
            Row0Control.SetValue(MarginProperty, new Thickness(0, 0, 0, 6));
        }
        else
        {
            Row0Control.SetValue(MarginProperty, new Thickness(0, 0, 0, 14));
        }
        oldCount = RootGrid.Children.Count;
    }         
   
}

在后面的代码中添加元素

private void Button_Click(object sender, RoutedEventArgs e)
{
    var Row1Control = new Rectangle() { Height = 80, Margin = new Thickness(0, 0, 0, 14), Fill = new SolidColorBrush(Colors.Black), Name = "Row1Control" };
    Row1Control.SetValue(Grid.ColumnProperty, 1);
    Row1Control.SetValue(Grid.RowProperty, 1);
    RootGrid.Children.Add(Row1Control);

}