c# - 当获取 textBlock 的高度时,无论实际高度如何,它都会说相同的数字

标签 c# wpf

我正在制作一个 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 中(而不是两个),那么它会为您整理出垂直对齐方式。然后你可以左对齐左边的消息,右对齐右边的消息。作为额外的好处,这意味着双方都有更多的宽度可以玩。但如果您不喜欢那样,您可以限制 TextBlockMaxWidth

我还强烈建议您考虑使用 MVVM 和绑定(bind),而不是在代码隐藏中手动创建控件。同样,这将使您远离对不需要的事情进行微观管理。

关于c# - 当获取 textBlock 的高度时,无论实际高度如何,它都会说相同的数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51315965/

相关文章:

c# - 将每个对象的特定变量显示到组合框中

wpf - MVVM 主窗口控件从子用户控件绑定(bind)

c# - 想要删除合法页面格式顶部的大边距

c# - 为什么 EventArgs 不是接口(interface)而是类?

c# - 使用 X509 证书通过 Azure AD 对应用程序进行身份验证

c# wpf comboBox 在我输入第一个字母时选择列表中的项目

c# - 从 C# WPF 中的另一个类访问控件的属性

c# - sharepoint 中的调查结果

c# - 新的 Outlook 邮件消息不加载

c# - UserControl 上的 SizeToContent