This is a test code that might do what you want or at least give you some ideas.
In the bottom part of the screen, you can change the margin, width and height of the text block in the upper part.
The code is calculating the move of the left/top position of the text block. The Padding of the text block is then set to compensate for that move. If the text goes outside the left or top side of the text block, padding is set to 0 and it will follow the text block. You have to take care of what to do if the text goes outside the right / bottom of the text block.
The calculation is done in the LayoutUpdated event handler which is called after all layout arrangements are done in the panel.
XAML:
<Grid x:Name="grid" LayoutUpdated="Grid_LayoutUpdated">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock x:Name="textBlock" Text="Test" Height="50" Width="100"/>
<StackPanel Grid.Row="1">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Margin" Width="100" Margin="5"/>
<TextBox Text="{Binding Margin, ElementName=textBlock, Mode=TwoWay}" Margin="5"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Width" Width="100" Margin="5"/>
<TextBox Text="{Binding Width, ElementName=textBlock}" Margin="5"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Height" Width="100" Margin="5"/>
<TextBox Text="{Binding Height, ElementName=textBlock}" Margin="5"/>
</StackPanel>
</StackPanel>
</Grid>
Code behind:
public partial class MainWindow : Window
{
public MainWindow()
{
DataContext = this;
InitializeComponent();
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
lastTextBlockPos = textBlock.PointToScreen(new Point());
initiateReady = true;
}
bool initiateReady = false;
Point lastTextBlockPos = new Point();
private void Grid_LayoutUpdated(object sender, EventArgs e)
{
if (initiateReady)
{
Point tp = textBlock.PointToScreen(new Point());
if (tp != lastTextBlockPos)
{
//Calculate how much the top left corner of the text block moved during layout.
double left = textBlock.Padding.Left - tp.X + lastTextBlockPos.X;
double top = textBlock.Padding.Top - tp.Y + lastTextBlockPos.Y;
//Set the padding to move the text inside the text block
//If outside the text block, set to left, top most position
//TODO: take care of when the text is outside on the right, bottom side
Thickness tn = new Thickness()
{
Left = left >= 0 ? left : 0,
Top = top >= 0 ? top : 0,
};
textBlock.Padding = tn;
lastTextBlockPos = tp;
//Showing TextBlock bounds for test
Point gp = grid.PointToScreen(new Point());
RectangleGeometry myRectangleGeometry = new RectangleGeometry();
myRectangleGeometry.Rect = new Rect(tp.X - gp.X, tp.Y - gp.Y, textBlock.ActualWidth, textBlock.ActualHeight);
Path myPath = new Path();
myPath.Data = myRectangleGeometry;
myPath.Stroke = Brushes.Goldenrod;
myPath.StrokeThickness = 2;
Grid.SetColumn(myPath, 0);
Grid.SetRow(myPath, 0);
Path old = grid.Children.OfType<Path>().FirstOrDefault();
if (old != null) grid.Children.Remove(old);
grid.Children.Add(myPath);
}
}
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…