Daniele Sartori
Daniele Sartori

Reputation: 1703

How to prevent TextBlock taking all the available space

Here is my problem. I've built the following ListView

<ListView Grid.Row="1" x:Name="messageList" BorderThickness="0"
                  ItemsSource="{Binding MySource}" 
                  HorizontalContentAlignment="Stretch">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="5*"/>
                        <ColumnDefinition Width="5*"/>
                    </Grid.ColumnDefinitions>
                    <WrapPanel Grid.Row="0" Grid.Column="0">
                        <TextBlock  Margin="2" 
                                VerticalAlignment="Center" 
                                Text="{Binding Received.SenderId}" 
                                />
                        <TextBlock  Margin="2" 
                                VerticalAlignment="Center" 
                                Text="{Binding Received.DeliverDate}" 
                               />
                    </WrapPanel>

                    <TextBlock Margin="2" 
                                VerticalAlignment="Center" 
                                Text="{Binding Received.MsgText}"
                                Grid.Row="1" Grid.Column="0"
                                TextWrapping="WrapWithOverflow">

                    </TextBlock>

                    <WrapPanel Grid.Row="0" Grid.Column="1">
                        <TextBlock  Margin="2" 
                                VerticalAlignment="Center" 
                                Text="{Binding Sent.SenderId}" 
                                />
                        <TextBlock  Margin="2" 
                                VerticalAlignment="Center" 
                                Text="{Binding Sent.DeliverDate}" 
                                />
                    </WrapPanel>

                    <TextBlock Margin="2" 
                                VerticalAlignment="Center" 
                                Text="{Binding Sent.MsgText}"
                                Grid.Row="1" Grid.Column="1"
                                TextWrapping="WrapWithOverflow">

                    </TextBlock>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

For each element of MySource only 1 between Received and Sent will be not null. The ListViewis working as i expect, placing the element on the left or the right of the screen, but the TextBlock that contain the MsgText get all the available space (so the whole row) if the message is too long. How can i limit it to stay only in one half of the parent Grid and make the text overflow eventually?

EDIT: I added an image showing my problem. The 4th message should overflow, but it doesn't

this is how it looks

Upvotes: 0

Views: 258

Answers (2)

Sinatr
Sinatr

Reputation: 21969

It took me few minutes to produce mcve, but the missing part of the puzzle is this:

<Grid MaxWidth="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}">

That would limit maximum width of all Grids (each item has one) and let wrapping happens. Otherwise Grid is asking for a width to fit whole item in one line and ListView is ok with it, but then you will see horizontal scrollbar (the most hated control by users including me).


MCVE:

public partial class MainWindow : Window
{
    public class Item
    {
        public string Received { get; set; }
        public string Sent { get; set; }
    }

    public List<Item> Items { get; }

    public MainWindow()
    {
        InitializeComponent();
        Items = new List<Item>
        {
            new Item { Received = "1111 111 11 111 11 1" },
            new Item { Received = "2222 2 22 2  2 222222222 2 222222 22222222 222222222222 2" },
            new Item { Sent = "333333333 3333333 333   33333 3  3 33 333333333 3333" },
            new Item { Received = "444444444444444 444 44444444444444 44  4 44444444444444444 4 4 4444444444 4 444   444444444444" },
        };
        DataContext = this;
    }
}

Screenshot:

Xaml:

<ListView ItemsSource="{Binding Items}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid MaxWidth="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <TextBlock Text="{Binding Received}"
                           TextWrapping="WrapWithOverflow" />
                <TextBlock Grid.Column="1"
                           Text="{Binding Sent}"
                           TextWrapping="WrapWithOverflow" />
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="HorizontalContentAlignment"
                    Value="Stretch" />
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

Upvotes: 1

Guilhem Prev
Guilhem Prev

Reputation: 979

The problem is that your grid (and the width of the column) is calculated for each element of your list, so it takes the most space possible. I propose a backup solution, I did not find better but the result is there.

This is to place 2 ListView in 2 columns of a grid and then have the Received element in one and the Sent in the other.

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <ListView Grid.Column="0" x:Name="messageListReceived" BorderThickness="0"
              ItemsSource="{Binding MySource}" 
              HorizontalContentAlignment="Stretch">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <WrapPanel Grid.Row="0">
                        <TextBlock  Margin="2" 
                                    VerticalAlignment="Center" 
                                    Text="{Binding Received.SenderId}" 
                        />
                        <TextBlock  Margin="2" 
                                    VerticalAlignment="Center" 
                                    Text="{Binding Received.DeliverDate}" 
                        />
                    </WrapPanel>

                    <TextBlock Margin="2" 
                               VerticalAlignment="Center" 
                               Text="{Binding Received.MsgText}"
                               Grid.Row="1"
                               TextWrapping="WrapWithOverflow">

                    </TextBlock>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    <ListView Grid.Column="1" x:Name="messageListSent" BorderThickness="0"
              ItemsSource="{Binding MySource}" 
              HorizontalContentAlignment="Stretch">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <WrapPanel Grid.Row="0">
                        <TextBlock  Margin="2" 
                                    VerticalAlignment="Center" 
                                    Text="{Binding Sent.SenderId}" 
                        />
                        <TextBlock  Margin="2" 
                                    VerticalAlignment="Center" 
                                    Text="{Binding Sent.DeliverDate}" 
                        />
                    </WrapPanel>

                    <TextBlock Margin="2" 
                               VerticalAlignment="Center" 
                               Text="{Binding Sent.MsgText}"
                               Grid.Row="1"
                               TextWrapping="WrapWithOverflow">

                    </TextBlock>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

Upvotes: 0

Related Questions