你需要以编程的方式完成此操作,而不是在xaml中进行。这是因为你想要它做两件不同的事情:
- 如果只有少量项目,则将最后一个TextBlock保持靠近DataGrid。
- 如果DataGrid有大量项目,则保持最后一个TextBlock可见。
要实现这一点,你需要在代码后台中钩入事件,确定最后一个TextBlock是否消失,然后相应地调整RowDefinition上的Height="Auto"或Height="*",然后UpdateLayout。
这是一个示例项目。我用TextBlock替换了你的DataGrid,以简化问题。
XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Content="Make Grid.Row=2 Long, But Keep Text 3 Visible" Click="Button_Click" HorizontalAlignment="Center" Margin="5" Padding="5,10"/>
<Grid Grid.Row="1" x:Name="myGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition x:Name="myRowDefinition" Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="This is Text 1" Background="Red"/>
<TextBlock Grid.Row="1" Text="This is Text 2" Background="Green"/>
<TextBlock Grid.Row="2" x:Name="myDataGrid" FontSize="64" Text="{Binding Output}" TextWrapping="Wrap" Background="Blue"/>
<TextBlock Grid.Row="3" x:Name="lastTextBlock" Text="This is Text 3" Background="Violet"/>
</Grid>
</Grid>
代码后台:
public partial class MainWindow : Window, INotifyPropertyChanged
{
private string output;
public MainWindow()
{
InitializeComponent();
this.Loaded += OnLoaded;
this.DataContext = this;
}
private void MyDataGrid_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (!IsUserVisible(lastTextBlock, this))
{
if (this.myRowDefinition.Height == GridLength.Auto)
{
this.myRowDefinition.Height = new GridLength(1, GridUnitType.Star);
}
}
else
{
if (this.myRowDefinition.Height != GridLength.Auto && CanDataGridBeSmaller(this.myRowDefinition.ActualHeight))
{
this.myRowDefinition.Height = GridLength.Auto;
}
}
this.UpdateLayout();
}
private bool CanDataGridBeSmaller(double actualHeight)
{
TextBlock dummy = new TextBlock() { TextWrapping = TextWrapping.Wrap, FontSize = 64, Text = this.Output };
dummy.Measure(new Size(this.myGrid.ActualWidth, this.myGrid.ActualHeight));
if (dummy.DesiredSize.Height < myRowDefinition.ActualHeight)
return true;
return false;
}
private bool IsUserVisible(FrameworkElement element, FrameworkElement container)
{
if (!element.IsVisible)
return false;
Rect bounds = element.TransformToAncestor(container).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight));
Rect rect = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight);
return rect.Contains(bounds);
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
this.myDataGrid.SizeChanged += MyDataGrid_SizeChanged;
this.Output = "This row is short, so Text 3 below me should be flush with my bottom.";
}
public event PropertyChangedEventHandler PropertyChanged;
public string Output { get => this.output; set { this.output = value; this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Output))); } }
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Output = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
}
}
当你开始时的示例输出:
点击顶部按钮后的示例输出: