Search code examples
c#xamllistviewuwptextblock

uwp TextBlock height problem in a single line


I have a sort of chat like feature in a uwp app, some chat messages can have long texts, hence they will be multiline, and some will have small texts hence single line.

The issue I am having is that textblock with single line has extra space left on bottom of it, probably because of textblock extra unnecessary height, meanwhile multiline textblock has same margin left above and below it (as you can see in the image below). I want uniform margins for single line textblocks as well.

chat msgs

In below image look closely the bottom side of multiline text has less space and bottom side of single line text has more space.

different margins appearing

I tried to fix it by setting VerticalContentAlignment of the ListViewItems to Top that solved this issue but created a vertical margin issue as you can see in the image below vertical margins between items is inconsistent :

vertical margin issue

Below is the relevant code.

MainPage

<Page
x:Class="ChatMarginBug.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:ChatMarginBug"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">

<Page.Resources>
    <Style x:Key="ChatListViewStyle" TargetType="ListView">
        <Setter Property="HorizontalAlignment" Value="Stretch" />
        <Setter Property="SelectionMode" Value="None" />
        <Setter Property="ItemContainerStyle">
            <Setter.Value>
                <Style TargetType="ListViewItem">
                    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                    <Setter Property="VerticalContentAlignment" Value="Top" />
                    <Setter Property="HorizontalAlignment" Value="Stretch" />
                    <Setter Property="Margin" Value="12,2,12,2" />
                </Style>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>

<Grid>

    <ListView ItemsSource="{x:Bind MyTweets}" Style="{StaticResource ChatListViewStyle}">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="local:TweetData">
                <Grid HorizontalAlignment="{x:Bind MyTweetType, Converter={StaticResource TweetTypeToHAConverter1}}" x:DefaultBindMode="OneWay">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="{x:Bind MyTweetType, Converter={StaticResource TweetTypeToC1DefConverter1}}" />
                        <ColumnDefinition Width="{x:Bind MyTweetType, Converter={StaticResource TweetTypeToC2DefConverter1}}" />
                    </Grid.ColumnDefinitions>
                    <Grid Grid.Column="{x:Bind MyTweetType, Converter={StaticResource TweetTypeToMetaDataColumnConverter1}}">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <TextBlock
                            Margin="0,0,0,4"
                            HorizontalAlignment="Center"
                            FontSize="{StaticResource TinyFontSize}"
                            FontWeight="Bold"
                            Foreground="{ThemeResource ApplicationSecondaryForegroundThemeBrush}"
                            Text="Name" />
                        <TextBlock
                            Grid.Row="1"
                            HorizontalAlignment="Center"
                            FontSize="{StaticResource TinyFontSize}"
                            Foreground="{ThemeResource ApplicationSecondaryForegroundThemeBrush}"
                            Text="15:00" />
                    </Grid>
                    <Grid
                        Grid.Column="{x:Bind MyTweetType, Converter={StaticResource TweetTypeToMsgColumnConverter1}}"
                        MinWidth="120"
                        Background="{x:Bind MyTweetType, Converter={StaticResource TweetTypeToColorConverter1}}">
                        <TextBlock
                            Margin="16,8,16,8"
                            FontSize="{StaticResource SmallFontSize}"
                            FontWeight="Normal"
                            Text="{x:Bind Text}"
                            TextTrimming="CharacterEllipsis"
                            TextWrapping="WrapWholeWords" />
                    </Grid>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>
</Page>

MainPage.xaml.cs

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        InitializeComponent();
        MyTweets = new List<TweetData>
        {
            new TweetData{ Text="abqrwfsddggc", MyTweetType = TweetType.Mine},
            new TweetData{ Text="abqrwfsddggasasasc", MyTweetType = TweetType.Mine},
            new TweetData{ Text="abqrwfsddassqsasacbvretgergggc", MyTweetType = TweetType.Mine},
            new TweetData{ Text="abcalkdjdjjd qdjqwpodwqpodqwjdqwkj qdkjqwkdjqwlkdjqlkdjaslkj   qieoqieowqdjwkjwkj kdwqjqwlk;lqwkd;lkd;laskd;laks;dlkaskld;lakdpoiwdpowqkd;l qwioeqwijdkqwjdlkndlksanlcsmcsa qwkkjeqwjdlkqwjdlksadmasldjl;qkd;asljdlqwkhdlwqk", MyTweetType = TweetType.Mine},
            new TweetData{ Text="abcalkdjkjwkj kdwqjqwlk;lqwkd;lkd;laskd;laks;dlkaskld;lakdpoiwdpowqkd;l qwioeqwijdkqwjdlkndlksanlcsmcsa qwkkjeqwjdlkqwjdlksadmasldjl;qkd;asljdlqwkhdlwqk", MyTweetType = TweetType.Mine},
            new TweetData{ Text="abewqeqweqweqwe", MyTweetType = TweetType.Mine},
            new TweetData{ Text="abcalkdjdjjd qdjqwpodwqpodqwjdqwkj qdkjqwkdjqwlkdjqlkdjaslkj   qieoqieowqdjwkjwkj kdwqjqwlk;lqwkd;lkd;laskd;laks;dlkaskld;lakdpoiwdpowqkd;l qwioeqwijdkqwjdlkndlksanlcsmcsa qwkkjeqwjdlkqwjdlksadmasldjl;qkd;asljdlqwkhdlwqk", MyTweetType = TweetType.Mine},
            new TweetData{ Text="abcalkdjdjjd qdjqwpodwqpodqwjdqwkj qdkjqwkdjqwlkdjqlkdjaslkj   qieoqieowqdjwkjwkj kdwqjqwlk;lqwkd;lkd;laskd;laks;dlkaskld;lakdpoiwdpowqkd;l qwioeqwijdkqwjdlkndlksanlcsmcsa qwkkjeqwjdlkqwjdlksadmasldjl;qkd;asljdlqwkhdlwqk", MyTweetType = TweetType.NotMine},
            new TweetData{ Text="abc", MyTweetType = TweetType.NotMine},
            new TweetData{ Text="abcqdwqdqdqsdqwdwqdsdsaddz", MyTweetType = TweetType.Mine},
            new TweetData{ Text="abc", MyTweetType = TweetType.NotMine},
            new TweetData{ Text="abcscascqwdwwrewr", MyTweetType = TweetType.NotMine},
            new TweetData{ Text="abc", MyTweetType = TweetType.NotMine},
            new TweetData{ Text="abc", MyTweetType = TweetType.NotMine},
            new TweetData{ Text="abcqweqwewqeqweqdsdadqwqw", MyTweetType = TweetType.NotMine},
            new TweetData{ Text="xkwjdwqjdpo", MyTweetType = TweetType.NotMine}
        };
    }

    public List<TweetData> MyTweets { get; }
}

Models

public class TweetData
{
    public string Text { get; set; }
    public TweetType MyTweetType { get; set; }
}

public enum TweetType { Mine, NotMine }

Please note that all the UI converters are for horizontal alignment and colors etc and doesn't mess with height or vertical alignments as you can already see in xaml above. I have prepared a sample app for this so you can test it yourself:

https://github.com/touseefbsb/ChatMarginBug


Solution

  • You can set the MinHeight of the ListViewItem to remove extra space left on bottom of textblock:

    <Setter.Value>
                        <Style TargetType="ListViewItem">​
                            <Setter Property="HorizontalContentAlignment" Value="Stretch" />​
                            <Setter Property="VerticalContentAlignment" Value="Stretch" />​
                            <Setter Property="HorizontalAlignment" Value="Stretch" />​
                            <Setter Property="Margin" Value="12,2,12,2" />​
                            <Setter Property="MinHeight" Value="20"></Setter>​
                        </Style>​
    </Setter.Value>