我正在制作一个 WPF 聊天程序,我想要显示消息的方式是这样的 (screenshot of how I have it now):
Sent Message
Received Message
Sent message2
Received Message
我在做什么:
一个滚动查看器,内部有一个网格,网格内部有 2 个堆栈面板,一个用于左侧,一个用于右侧。
<ScrollViewer x:Name="scrlViewer" VerticalScrollBarVisibility="Hidden" Width="472" Margin="10,10,0,67"
HorizontalAlignment="Left" Grid.ColumnSpan="2">
<Grid x:Name="ScrollViewerChild">
<StackPanel x:Name="ChatRow1" Width="200" Margin="10,10,0,10" HorizontalAlignment="Left" />
<StackPanel x:Name="ChatRow2" Width="200" Margin="0,10,10,10" HorizontalAlignment="Right"/>
</Grid>
</ScrollViewer>
然后在添加消息时,我制作了一个边框,然后制作了一个 TextBlock。然后我将文本 block 添加到边框,然后将边框添加到相应的堆栈面板。
然后我尝试获取 TextBlock 的高度(或边框,两者都会发生同样的事情)并制作 2 个不透明度为 0 的分隔符。高度 10 之一添加到消息被添加到的面板,另一个是 textBlockHeight + 10 到没有添加任何内容的面板。
public void PrintOwnMessage(string msg)
{
var border = new Border()
{
Margin = new Thickness(0),
Padding = new Thickness(10,0,0,0),
BorderThickness = new Thickness(1),
BorderBrush = Brushes.White,
Background = Brushes.Azure,
CornerRadius = new CornerRadius(5)
};
var textBlock = new TextBlock()
{
Text = msg,
FontSize = 20,
TextWrapping = TextWrapping.Wrap
};
Console.WriteLine(border.DesiredSize);
border.Child = textBlock;
//panel[0] is the rightside panel where this function adds the message to
panel[0].Children.Add(border);
msgHeight = textBlock.ActualHeight;
textBlock.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
var desiredSizeNew = textBlock.DesiredSize;
msgHeight = desiredSizeNew.Height + 10;
panel[0].Children.Add(new Separator() { Opacity = 0, Height = 10});
panel[1].Children.Add(new Separator() { Opacity = 0, Height = msgHeight });
scrl.ScrollToEnd();
}
问题:
“desiredSizeNew”变量似乎每次都一样。请注意,我以这种方式获取大小,因为尝试获取 .Height 给我一个 NaN,而 .ActualHeight 总是返回一个零。
它总是给我一行的大小(“26.6”),即使消息换行到多行,所以只要消息只有 1 行高度,代码就可以工作。
任何帮助将不胜感激! 我希望我能够很好地解释我的问题。这是我第一次用 C# 做任何事情,所以任何关于更好的方法来实现我想要的东西的建议都会很棒。虽然我想先知道如何解决这个问题。
最佳答案
要回答这个问题,DesiredSize
不是 ActualHeight
,在 WPF 完成其测量和排列过程之前,它不会有最终值。
但无论如何您都不想这样做,因为没有什么可以阻止这些值发生变化。例如,如果屏幕旋转,那么宽度可能会改变,这会改变包装,这会改变实际高度......这意味着设置为占位符高度的计算高度现在是错误的。
您正在尝试对布局进行微观管理。让 WPF 为您做这件事。布置事物是 WPF 的工作,而且它非常擅长于此。但是你必须正确地描述布局。完成此操作后,WPF 将负责在情况发生变化时进行调整。如果您发现自己尝试设置宽度或高度,您通常需要更加认真地考虑布局。有时您必须这样做,但这种情况很少见。
基本上,您已经并排定义了两个 StackPanel
。每次向一侧添加一条消息时,您都会在下方添加一个分隔符,并且您试图通过放置相应的高分隔符来手动保持另一侧同步。
如果您将两侧的项目放在一个 StackPanel
中(而不是两个),那么它会为您整理出垂直对齐方式。然后你可以左对齐左边的消息,右对齐右边的消息。作为额外的好处,这意味着双方都有更多的宽度可以玩。但如果您不喜欢那样,您可以限制 TextBlock
的 MaxWidth
。
我还强烈建议您考虑使用 MVVM 和绑定(bind),而不是在代码隐藏中手动创建控件。同样,这将使您远离对不需要的事情进行微观管理。
关于c# - 当获取 textBlock 的高度时,无论实际高度如何,它都会说相同的数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51315965/