Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当获取文本块的高度时,无论实际高度如何,它都会显示相同的数字_C#_Wpf - Fatal编程技术网

C# 当获取文本块的高度时,无论实际高度如何,它都会显示相同的数字

C# 当获取文本块的高度时,无论实际高度如何,它都会显示相同的数字,c#,wpf,C#,Wpf,我正在制作一个WPF聊天程序,我希望显示消息的方式如下(): 我在做什么: 一个滚动查看器,在网格内部和网格内部有两个堆叠面板,一个用于左侧,一个用于右侧 <ScrollViewer x:Name="scrlViewer" VerticalScrollBarVisibility="Hidden" Width="472" Margin="10,10,0,67" HorizontalAlignment="Left" Grid.ColumnSpan="2"

我正在制作一个WPF聊天程序,我希望显示消息的方式如下():


我在做什么:

一个滚动查看器,在网格内部和网格内部有两个堆叠面板,一个用于左侧,一个用于右侧

<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>

问题:

“desiredSizeNew”变量似乎每次都是相同的。请注意,我这样得到尺寸是因为试图得到.Height会给我一个NaN,而.ActualHeight总是返回一个零

它总是给我一行(“26.6”)的大小,即使消息包装成多行,因此只要消息只有一行高度,代码就可以工作


任何帮助都将不胜感激!
我希望我能很好地解释我的问题。这是我第一次用c#做任何事情,所以任何关于实现我想要的更好的方法的建议都会很好。尽管我想知道如何首先解决这个问题。

我会回答“任何关于更好地实现我想要的目标的建议都会很好”

我认为您应该尝试使用DataTemplate。在代码隐藏中创建元素通常会导致糟糕的结果(大量的工作、未使用的部分、错误行为等)

我的示例基于DataTemplate和两个简单类:

public class Message
{
    public string content { get; set; }
    public Message(string content)
    {
        this.content = content;
    }
}

public class MsgSent:Message
{
    public MsgSent(string content) : base(content) { }
}
public class MsgRecieved : Message
{
    public MsgRecieved(string content) : base(content) { }
}
MsgSent
MsgRecieved
完全相似。但是我们可以想象你聊天时的不同行为。最重要的是,对于DataTemplate,我需要两个不同的类

    <ListView ItemsSource="{Binding}" Name="viewChat" HorizontalContentAlignment="Stretch">
        <ListView.Resources>
            <DataTemplate DataType="{x:Type local:MsgRecieved}">
                <Border  Background="LightGreen" Width="Auto" HorizontalAlignment="Left" CornerRadius="5" Margin="1">
                    <TextBlock Text="{Binding content}" Margin="5"/>
                </Border>
            </DataTemplate>
            <DataTemplate DataType="{x:Type local:MsgSent}">
                <Border  Background="LightBlue" Width="Auto" HorizontalAlignment="Right" CornerRadius="5" Margin="1">
                    <TextBlock Text="{Binding content}" Margin="5"/>
                </Border>
            </DataTemplate>
        </ListView.Resources>
    </ListView>

我使用了一个ObservableCollection,因此您可以动态填充它。

为了回答这个问题,
DesiredSize
不是
实际高度,在WPF完成其测量和排列过程之前,不会有最终值

但无论如何,您都不会希望这样做,因为没有任何东西可以阻止这些值的更改。例如,如果屏幕旋转,那么宽度可能会改变,这将改变包装,这将改变实际高度…这意味着设置为占位符高度的计算高度现在是错误的

你在试图微观管理布局。让WPF为您做这件事。布局是WPF的工作,而且非常擅长。但是你必须正确地描述布局。一旦你做到了这一点,WPF将在事情发生变化时进行调整。如果您发现自己试图设置宽度或高度,通常需要更仔细地考虑布局。有时你必须这样做,但这应该是罕见的

基本上,您已经定义了两个并排的
StackPanel
s。每次消息添加到一侧时,您都会在下面添加一个分隔符,并试图通过放置相应的高分隔符手动保持另一侧的同步

如果您将两侧的项目放置在一个
堆叠面板中(而不是两个),那么它将为您整理垂直对齐。然后,您可以将消息向左对齐,将消息向右对齐。作为一个额外的好处,这意味着双方都有更多的宽度可以玩。但是如果您不喜欢,可以限制
TextBlock
s的
MaxWidth


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

谢谢!我从来没有听说过MVVM,现在我正在读这篇文章。非常感谢!这很好,而且比我之前做的要简单得多:D
public class Message
{
    public string content { get; set; }
    public Message(string content)
    {
        this.content = content;
    }
}

public class MsgSent:Message
{
    public MsgSent(string content) : base(content) { }
}
public class MsgRecieved : Message
{
    public MsgRecieved(string content) : base(content) { }
}
    <ListView ItemsSource="{Binding}" Name="viewChat" HorizontalContentAlignment="Stretch">
        <ListView.Resources>
            <DataTemplate DataType="{x:Type local:MsgRecieved}">
                <Border  Background="LightGreen" Width="Auto" HorizontalAlignment="Left" CornerRadius="5" Margin="1">
                    <TextBlock Text="{Binding content}" Margin="5"/>
                </Border>
            </DataTemplate>
            <DataTemplate DataType="{x:Type local:MsgSent}">
                <Border  Background="LightBlue" Width="Auto" HorizontalAlignment="Right" CornerRadius="5" Margin="1">
                    <TextBlock Text="{Binding content}" Margin="5"/>
                </Border>
            </DataTemplate>
        </ListView.Resources>
    </ListView>
ObservableCollection<Message> letsChat = new ObservableCollection<Message>();
letsChat.Add(new MsgRecieved("Hello world! \nHow are you?"));
letsChat.Add(new MsgSent("Hi, good to see you!"));
letsChat.Add(new MsgSent("Hey, are you still there?"));
letsChat.Add(new MsgSent("Please let me know when you are back."));
letsChat.Add(new MsgRecieved("Hello world! \nHow are you?"));

viewChat.DataContext = letsChat;