windows phone 7 TextBlock TextWrapping not honored in listbox - silverlight

I have a listbox defined as :
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="myListBox" Width="468" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Template>
<ControlTemplate>
<ScrollViewer Width="468">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
</ListBox>
</Grid>
In the code, I create multiple textBlocks as the Listbox Items with textWrapping enabled in each textBlock.
for (int i = 0; i < everyLine.Length; i++)
{
TextBlock txtBlock = new TextBlock()
{
TextWrapping = TextWrapping.Wrap,
Name = "textBlock" + i,
Foreground = textBrush,
FontSize = 20,
Text = everyLine[i]
};
this.myListBox.Items.Add(txtBlock);
}
But, none of the text in any of the text blocks gets wrapped.
Can somebody please let me know if the above way of defining textBlocks in listbox is incorrect?

+1 for Derek's answer
Also, please be careful using the <StackPanel> in your ListBox. By default, the ListBox uses a <VirtualizingStackPanel> and this is very important as it uses significantly less UI resources (memory) when displaying long lists.

Is there any particular reason why you are adding elements in code? By the looks of things you have a data collection, which you can set ast teh ItemsSource of the ListBox and then use an ItemTemplate to specify what each item should look like. Something like the following:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="myListBox" Width="468">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock FontSize="20" Text="{Binding}" TextWrapping="Wrap" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Note, that the default style for the ListBox already includes the ScrollViewer so there's no need to change the ControlTemplate. Because you've already fixed the width of the ListBox, the above should "just work".

Related

WPF disable ListBox autosizing in uniform grid

i do have the following structure:
<UniformGrid HorizontalAlignment="Stretch" Grid.Row="0" VerticalAlignment="Top" Columns="6" DockPanel.Dock="Right" >
<StackPanel HorizontalAlignment="Stretch">
<DockPanel Background="#FF393939" >
<Label Content="{lex:Loc Site}" Foreground="#FFE0E0E0"/>
</DockPanel>
<ListBox Height="300" ItemsSource="{Binding Sites.View}" DisplayMemberPath="Name.ActualTranslation">
</ListBox>
</StackPanel>...
These stackpanels in my UniformGrid should be spreaded over the whole MainWindow (or View)... Still if there is an item in a Listbox which has a longer string which needs more place than the standard width it autofits the string and i have to scroll vertically.
I dont want the listview to gain the width if the content has not enough place.
I also have a scrollviewer in my MainWindow in which this view is placed...
What can i do that the uniform grid stays the same width like the MainWindow-...
I've already tried to give a name to the MainWindow and Bind the width to something like this: Width="{Binding ElementName=MainWindow, Path=ActualWdith}" ..
though i get the error:
Cannot find source for binding with reference 'ElementName=MainWindow'. BindingExpression:Path=ActualWdith; DataItem=null;
What can i do to fix this issue?
If you need more information or my error description isnt clear dont hesitate to ask.
UPDATE:
how it should be:
behavior when the text is too long:
and a scrollbar appears on the bottom..
If you are trying to access a WPF object by name it needs to have x:Key="name" which wasn't shown in your code above, i.e.
<Window x:Name="MainWindow" ....
Alternatively you can walk back up the tree until you find an object of the correct type,
Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type MainWindow}, Path=ActualWidth}"
Alternatively you can simply change the way you show the text to constrain its width
<ListBox Height="300" ItemsSource="{Binding Sites.View}" DisplayMemberPath="Name.ActualTranslation">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" TextWrapping="Wrap" MaxWidth="200"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Looking for a WPF multicolumn list with scaling

I would like to create a multi-column list of checkboxes, but here's the catch - as I resize the window I would like everything to scale accordingly, including text size. I've been trying to make use of a WrapPanel and ViewBox but can't get the XAML right. Are these controls the best option or should I be using a ListBox (note I don't need selection functionality or scrollbars)? Any suggestions or examples on how I could achieve this would be much appreciated. I'm using MVVM and the list will be data bound, if that makes a difference.
BTW since starting WPF I've been struggling to understand which controls size to their children and which size to their parent. Are there any good sites, cheat sheets, or whatever summarising the behaviour of each control?
If you have a variable number of child elements, you could put a UniformGrid into a ViewBox.
If the child elements have to be visualized by a DataTemplate, you would have to use an ItemsControl with the ItemsPanel property set to such a UniformGrid:
<Viewbox Stretch="Uniform">
<ItemsControl ItemsSource="{Binding Items}" Width="400" Height="200">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="4"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="AliceBlue">
<CheckBox Content="{Binding Label}" IsChecked="{Binding IsChecked}"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Viewbox>

Silverlight 4 - simple control template

<DataTemplate x:Key="dirtSimple">
<TextBlock Margin="10,0,0,0" Text="{Binding Path=CurrentBook.Published, StringFormat=d}"></TextBlock>
</DataTemplate>
<ControlTemplate x:Key="lbWrapPanelTemplate">
<StackPanel Orientation="Horizontal" Margin="2" Background="Aqua">
<ItemsPresenter></ItemsPresenter>
</StackPanel>
</ControlTemplate>
...
<ListBox Template="{StaticResource lbWrapPanelTemplate}" x:Name="bookListBox" Grid.Row="0" ItemsSource="{Binding Path=BookSource}" ItemTemplate="{StaticResource dirtSimple}" >
</ListBox>
The list box is displaying correctly, with a beautiful "Aqua" background, and each item is boringly displayed with just a date. For some reason though the items are not flowing horizontally. I originally tried it with the Silverlight Toolkit's WrapPanel, with the same problem, but I can't even get it to work with a built-in StackPanel, so I suspect I'm missing something.
Are you trying to get selection-based behavior that a ListBox provides? If not, use an ItemsControl (and supply an ItemsPanel as below).
The reason it's not going horizontal is the ItemsPresenter ultimately has its own panel it lays out items in. It's not inserting each item separately into your StackPanel (or WrapPanel), it's putting them in its own panel
What you want to do is specify a value for ItemsPanel like so:
<ListBox ItemTemplate="{StaticResource dirtSimple}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>

Force TextBlock to wrap in WPF ListBox

I have a WPF listbox which displays messages. It contains an avatar on the left side and the username and message stacked vertically to the right of the avatar. The layout is fine until the message text should word wrap, but instead I get a horizontal scroll bar on the listbox.
I've Googled and found solutions to similar issues, but none of them worked.
<ListBox HorizontalContentAlignment="Stretch" ItemsSource="{Binding Path=FriendsTimeline}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Border BorderBrush="DarkBlue" BorderThickness="3" CornerRadius="2" Margin="3" >
<Image Height="32" Width="32" Source="{Binding Path=User.ProfileImageUrl}"/>
</Border>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Path=User.UserName}"/>
<TextBlock Text="{Binding Path=Text}" TextWrapping="WrapWithOverflow"/> <!-- This is the textblock I'm having issues with. -->
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Contents of the TextBlock can be wrapped using property TextWrapping.
Instead of StackPanel, use DockPanel/Grid.
One more thing - set ScrollViewer.HorizontalScrollBarVisibility property to Disabled value for the ListBox.
Updated Hidden to Disabled based on comment from Matt. Thanks Matt.
The problem might not be located in the ListBox. The TextBlock won't wrap, if one of the parent controls provides enough space, so that it hasn't the need to wrap. This might be caused by a ScrollViewer control.
If you want to prevent TextBlock to grow, and you want it to just fit in the size of the listbox, you should set the width of it explicitly.
In order to change it dynamically, it means not a fix value, but you need to bind it to its proper parent element in the visual tree. You can have something like this:
<ListBox ItemsSource="{Binding MyItems}" Name="MyListBox">
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="Width"
Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ScrollContentPresenter}, Path=ActualWidth}" />
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" TextWrapping="Wrap" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If it does not work, try to find the proper elements (which has to be binded to what) with the Live Visual Tree in Visual Studio.

How to space items evenly in a horizontal Silverlight Listbox

In Silverlight, I have a Vertical ListBox that has a Horizontal ListBox for each item. I want the items in the HorizontalListbox to space evenly across the width of the parent (Vertical) ListBox. How can I do this?
<ListBox x:Name="MachineListBox" Background="Green">
<ListBox.ItemTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding CoilList}" Background="Red" HorizontalAlignment="Stretch">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel
HorizontalAlignment="Stretch" />
</ItemsPanelTemplate >
</ListBox.ItemsPanel>
<ListBox.ItemTemplate >
<DataTemplate>
<TextBlock
Text="{Binding Coil}"
HorizontalAlignment="Stretch"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I'll take the liberty of suggesting you use a custom control of my own invention. It's called a ProportionalPanel and it does just what you need - spaces items evenly. You could use it for the ItemsPanel in the inner ListBox instead of the StackPanel. I also provide the source code, so you can tweak the logic any way you like. The relevant post on my blog is here.
I think the proportional sizing operator will do what you're looking for. Haven't tried it but it sounds like an option. Width="*" and Margin="2*".

Resources