1

I'm creating a very simple chat program (mostly just to teach myself WPF) and I'm trying to make a ListBox where the elements (strings representing the chat history) are displayed bottom to top and the Text inside the list box wraps. I've seen a few solutions for both of these problems separately, but they seem to require setting the ListBox.ItemsPanel, which I can only do once. As I'm still pretty new to WPF, I'm not sure how to go about actually getting the functionality for both of these things to work together. Is there a property on VirtualizingStackPanel that can simply be set to do this? Do I need to create a data template to achieve this?

Here's my XAML that has the content in the ListBox actually going from Bottom to Top.

<ListBox x:Name="lbChatHistory" ItemsSource="{Binding History}">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel VerticalAlignment="Bottom" />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>
JSicking84
  • 55
  • 1
  • 6

1 Answers1

2

You need to specify an ItemTemplate for the ListBox to use for each item. Then within that template one needs to have a TextBlock which has its property TextWrapping set to Wrap.

But real the problem, which is solved below, is that one runs into a situation where when first drawn the TextBlock will expand to the needed space. But after that it will not resize.

By binding to a parent which can resize (note that not all things do not resize automatically) we can get such a change.

One thing I like to do during the design phase is to give the items being styled specific colors to determine how things are drawn.

enter image description here

Code

<Grid Background="DarkGreen">
    <ListBox x:Name="lbChatHistory"
             ItemsSource="{StaticResource Orders}"
             HorizontalAlignment="Stretch"
             VerticalAlignment="Stretch"
             Background="DarkBlue"
             Margin="10">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel VerticalAlignment="Bottom" />
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding CustomerName, FallbackValue=Unknown}"
                            FontSize="14"
                            Foreground="White"
                            TextWrapping="Wrap"
                            Width="{Binding ElementName=lbChatHistory, Path=ActualWidth}"
                            VerticalAlignment="Stretch"
                            HorizontalAlignment="Stretch"
                            Background="DarkRed"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

For this example completeness the control is bound to a list of Orders with obvious properties, but your data will differ of course.

<Page.Resources>
    <model:Orders x:Key="Orders">
        <model:Order CustomerName="Alpha"
                        OrderId="997"
                        InProgress="True" />
        <model:Order CustomerName="Beta"
                        OrderId="998"
                        InProgress="False" />
        <model:Order CustomerName="Omega"
                        OrderId="999"
                        InProgress="True" />
        <model:Order CustomerName="The rain in spain falls mainly"
                        OrderId="1000"
                        InProgress="False" />
    </model:Orders>
</Page.Resources>

This answer is similar to an answer I gave ListBoxItem HorizontalContentAlignment To Stretch Across Full Width of ListBox which may be needed for your next question as you color the surrounding textblock.

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
  • Thank you very much for this response. I am running into one issue, which stems from my still somewhat new knowledge of DataBinding. When I add the suggested ListBox.ItemTemplate you provided, the output in the ListBox becomes the Fallback value of "Unknown". The ItemSource Binding for the ListBox itself points to an ObservableCollection of Strings called History. So, shouldn't I need to change the Binding for the TextBlock itself to be something different? My only guess is that it's confused because it can't find "History" inside of "History", if that makes sense... – JSicking84 Jan 16 '17 at 23:17
  • Actually, I just got this figured out... `Text="{Binding}"` worked. Not entirely sure I understand what it's doing so there's something new for me to look into, but it worked. – JSicking84 Jan 16 '17 at 23:32
  • @WannabeCoder that binding is for a list of strings where there is no property to bind to. By saying just "Binding" you are telling the parser to reflect off of the current `DataContext` with no property name supplied; to get the data. For my example, and most likely yours in the future where you will have actual instance objects with properties such as timestamp, font info etc, you will need to add a property name. Could you please mark my post as the answer since it shows someone how to create this list and handle the resize issue as well as binding. thx – ΩmegaMan Jan 17 '17 at 00:36