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);
}
我有一个 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);
}