I'd like to create a table on WP7. This is my current approach using a ListBox with a Grid as the data template.
<ListBox x:Name="ResultsList" Margin="12,0" Grid.Row="1">
<ListBox.Resources>
<DataTemplate x:Key="ResultsListItem">
<Grid d:DesignWidth="385" Height="28">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="88"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="textBlock1" Margin="0,0,24,0"/>
<TextBlock x:Name="textBlock2" Margin="0,0,24,0"
VerticalAlignment="Top" Grid.Column="1"/>
<TextBlock x:Name="textBlock3" Margin="0,0,24,0"
VerticalAlignment="Top" Grid.Column="3"/>
</Grid>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemTemplate>
<StaticResource ResourceKey="ResultsListItem"/>
</ListBox.ItemTemplate>
</ListBox>
The problem is, that the resulting table's columns are not sized equally. The Grid's column definitions are applied to each row independently of the other rows. That means, if there is a long text in textBlock1, column 0 will be larger. In the next row there could be a shorter text in textBlock1, resulting in column 0 also being shorter than the column 0 in the previous row.
How can the columns in all rows be sized equally? I don't want to use fixed width because when the orientation changes from portrait to landscape the colums would resize automatically.
There is the HeaderedItemsControl, but as I understand it it is not available for Windows Phone 7?
This is a tricky problem! In WPF there exists the concept of a SharedSizeGroup, which allows you to share column widths across multiple grids, but this is not available in silverlight.
There are a few workarounds on the web:
http://www.scottlogic.co.uk/blog/colin/2010/11/using-a-grid-as-the-panel-for-an-itemscontrol/
http://databaseconsultinggroup.com/blog/2009/05/simulating_sharedsizegroup_in.html
Although neither are simple solutions.
You might also try Mike's AutoGrid:
http://whydoidoit.com/2010/10/06/automatic-grid-layout-for-silverlight/
Here is my solution using SharedSizeGroup as suggested by ColinE.
<ListBox x:Name="ResultsList">
<ListBox.Resources>
<SharedSize:SharedSizeGroup x:Key="Col1Width" />
<SharedSize:SharedSizeGroup x:Key="Col2Width" />
<SharedSize:SharedSizeGroup x:Key="Col3Width" />
<DataTemplate x:Key="ResultsListItem">
<StackPanel d:DesignWidth="385" Orientation="Horizontal">
<SharedSize:SharedSizePanel WidthGroup="{StaticResource Col1Width}">
<TextBlock x:Name="textBlock" MaxWidth="100" Text="{Binding A}"/>
</SharedSize:SharedSizePanel>
<SharedSize:SharedSizePanel WidthGroup="{StaticResource Col2Width}">
<TextBlock x:Name="textBlock1" MaxWidth="85" Text="{Binding B}"/>
</SharedSize:SharedSizePanel>
<SharedSize:SharedSizePanel WidthGroup="{StaticResource Col3Width}">
<TextBlock x:Name="textBlock2" MaxWidth="200" Text="{Binding C}"/>
</SharedSize:SharedSizePanel>
</StackPanel>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemTemplate>
<StaticResource ResourceKey="ResultsListItem"/>
</ListBox.ItemTemplate>
</ListBox>
Even the maximum with of each column can be controlled via the TextBlock's MaxWidth property. The SharedSizeGroups ensure that the TextBlocks have the same size in each row.
You can use WrapPanel. Set the following ItemsPanel in the Datatemple, you can just have textblock.
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<control:WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
Related
I want a container that have 3 columns and in each column, the cell can wrap it's content like the picture below
So far, I've done this:
<ListBox Name="listQuestion">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="3"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
But the result is every cell have the same size as the biggest cell.
If you want to have a grid with three separate lists as their columns you should be able to use a combination of a Grid and a listbox
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox Grid.Column="0"/>
<ListBox Grid.Column="1"/>
<ListBox Grid.Column="2"/>
</Grid>
A grid will give you the most flexibility in your layout and allows you to have elements span multiple columns or rows. If you don't need all that flexibility you could use a stackpanel instead
<StackPanel Orientation="Horizonal">
<ListBox/>
<ListBox/>
<ListBox/>
</StackPanel>
I have a 3 Level Nested ListView binded to the same 3 Level Nested Collection. MainItems are added at the 3rd level.
Unmodified, there are scrollbars on ALL the levels. On item added, I edit the Containing Grid of the ListViewItem to adjust the height dynamically.
I have succeeded on removing the 3rd Level Scroll Bar. However, I want to remove the 2nd Level also, which I can't seem to do.
When I try to adjust the height of the 1st Level ListViewItem, the scrollbars on the 1st Level just disappears but the height is not adjusted at all.
What I want to do is ONLY have the ScrollBar on the 1st Level and scroll from there.
Basically, something like this:
This is my current code:
<Grid x:Name="ParentGrid">
<ListView x:Name="Level1ListView"
ItemsSource="{Binding Path=Level1}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid x:Name="GridLevel1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ToolKit_Controls:LayoutTransformControl Grid.Column="0">
<ToolKit_Controls:LayoutTransformControl.Transform>
<RotateTransform x:Name="rotateTransform" Angle="270"/>
</ToolKit_Controls:LayoutTransformControl.Transform>
<TextBlock Text="{Binding Path=Level1NameString}" FontSize="32" HorizontalAlignment="Center" />
</ToolKit_Controls:LayoutTransformControl>
<ListView x:Name="Level2ListView"
ItemsSource="{Binding Path=Level2}"
Grid.Column="1"
>
<ListView.ItemTemplate>
<DataTemplate>
<Grid x:Name="GridLevel2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border BorderBrush="White" BorderThickness="1" Grid.Row="0"/>
<TextBlock Text='{Binding Path=Level2Name}' Foreground="Black" FontSize="18"
Grid.Row="0"/>
<Grid x:Name="GridLevel3" Width="300" Height="100" Grid.Row="1">
<ListView x:Name="ListView_Level3" IsSwipeEnabled="False"
ManipulationMode="None"
ItemsSource="{Binding Path=Level3DisplayCollection}"
Grid.Column="1">
<ListView.ItemContainerTransitions>
<TransitionCollection>
<EntranceThemeTransition IsStaggeringEnabled="False" />
</TransitionCollection>
</ListView.ItemContainerTransitions>
</ListView>
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Horizontal" MaximumRowsOrColumns="1" ></WrapGrid>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
And the important code which changes the height on item added:
var GridLevel1 = TypedAssociatedObject.GetAncestors().Where(a => a.Named("GridLevel1")).FirstOrDefault() as Grid;
//GridLevel1.Height = GridLevel1.ActualHeight + 50;
var GridLevel2 = TypedAssociatedObject.GetAncestors().Where(a => a.Named("GridLevel2")).FirstOrDefault() as Grid;
GridLevel2.Height = GridLevel2.ActualHeight + 50;
var GridLevel3 = TypedAssociatedObject.GetAncestors().Where(a => a.Named("GridLevel3")).FirstOrDefault() as Grid;
GridLevel3.Height = GridLevel3.ActualHeight + 50;
Level 1 is commented out because when I add it, although the 2nd Scroll Bar is removed the ListViewItem height doesn't change, resulting in the UI being wrong and not showing everything. You also notice that the 1st level scrollbar remains the same size:
What I want is to extend the height of Header 1 so that everything still shows and the 1st Level Scrollbar on the right is the one that extends / grows.
Can anyone help point out what I am doing wrong?
Thank you!
Edit: This is a Windows store app.
Set the ItemsPanel to StackPanel in your inner list views. This way you would not need to adjust the height of each item.
Also to hide the scrollbars use ScrollViewer.VerticalScrollBarVisibility="Hidden" on your inner list views.
Have you considered using grouping?
I have a ListBox set up with automatic numbering as shown below. I want to format the number out front of each ListBoxItem so the numbers in all the rows are right aligned with each other. I figured I could use the item count to determine how many characters are in the index, using that info to set up a format in my viewmodel, and bind to it. Unfortunately I have not even figured out how to format a constant field width for my numbers. The ListBox will look a lot nicer with the contents lined up. So I need to know how to set up the format so I can bind to it.
<ListBox ItemsSource="{Binding Profiles}" SelectedItem="{Binding SelectedProfile, Mode=TwoWay}"
AlternationCount="{Binding Path=Profiles.Count}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0,0,5,0"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplatedParent.(ItemsControl.AlternationIndex)}"/>
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Your Profile type should have an Index property of some sort, which you should set. AlternationCount "enables alternating containers to have a unique appearance," so I believe you're not using that correctly. When you have that property added to your Profile type then you can do something for your ItemTemplate like:
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100">
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Right"
Margin="0 0 5 0"
Grid.Column="0"
Text="{Binding Index}"/>
<TextBlock Grid.Column="1"
Text="{Binding}" />
</Grid>
</DataTemplate>
I need to change Pivot header background and padding (top menu of Pivot control where are titles of pivot items).
I try this:
<controls:Pivot Grid.Row="1" Margin="0" Padding="0">
<controls:Pivot.HeaderTemplate>
<DataTemplate>
<StackPanel Background="#666666" Margin="0" />
</DataTemplate>
</controls:Pivot.HeaderTemplate>
<controls:PivotItem Background="#65006a">
<controls:PivotItem.Header>
<TextBlock FontSize="60" Margin="0">tasks</TextBlock>
</controls:PivotItem.Header>
</controls:PivotItem>
</controls:Pivot>
But it doesnt solve it.
How can I do this?
The proper way to do it is with the following snipped:
<controls:Pivot.HeaderTemplate>
<DataTemplate>
<StackPanel Background="#666666" Margin="0">
<TextBlock FontSize="60" Margin="0" Text="{Binding}"/>
</StackPanel>
</DataTemplate>
</controls:Pivot.HeaderTemplate>
<controls:PivotItem Background="#65006a" Header="tasks">
</controls:PivotItem>
Each PivotItem has header text which is then passed to the data template contained in HeaderTemplate. You can see that I've moved TextBlock inside StackPanel and set its text via binding. What you did wrong is that header template contained only StackPanel and nothing inside it.
Here, I have modified the header of a pivot control. I have defined different control with different colours so you can easily identify what I have done. Modify this source as per need to change pivot header.
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<phone:Pivot>
<phone:Pivot.HeaderTemplate>
<DataTemplate>
<StackPanel Background="Blue"
Margin="15,-10,0,0">
<TextBlock Text="{Binding}"
FontSize="20"
/>
</StackPanel>
</DataTemplate>
</phone:Pivot.HeaderTemplate>
<phone:PivotItem Header="item1">
<Grid Background="Red"></Grid>
</phone:PivotItem>
<phone:PivotItem Header="item2">
<Grid Background="Green"></Grid>
</phone:PivotItem>
</phone:Pivot>
</Grid>
I have a ListBox control that has been assigned to Grid.Column 0 which has a value of '*' defined for it's width, however when rendered there is a sizeable amount of space that is not being used.
I have also noticed that there is a border of sorts around the ListBox control itself, however I have not added one within the markup.
My UI (Areas of concern marked in Red):
My Markup:
<Window.Resources>
<DataTemplate x:Key="GameImagesTemplate" >
<StackPanel Orientation="Vertical">
<Image Source="{Binding FileInfo.FullName}" Margin="8,8,8,8" Height="70" Width="70" />
<Label Content="{Binding Name}" Width="70" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="GameTemplate">
<StackPanel>
<Label Content="{Binding Name}" Background="Gray" FontSize="16" />
<ListBox x:Name="imageContent" ItemsSource="{Binding FileList}" ItemTemplate="{StaticResource GameImagesTemplate}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ListBox x:Name="ContentList" ItemTemplate="{StaticResource GameTemplate}" Grid.Column="0" ScrollViewer.HorizontalScrollBarVisibility="Disabled" />
<StackPanel Grid.Column="1" Background="DarkGray">
<Button Click="OnLoad">_Load</Button>
<Button Click="OnSave">_Save</Button>
<Button Click="OnAdd">_Add</Button>
<Button Click="OnDelete">_Delete</Button>
</StackPanel>
</Grid>
How would I go about resolving both of the issues raised. Is it the default behaviour of the ListBox control?
Many thanks
Yes, that is the default behavior.
In the case of the alignment it looks like you have a WrapPanel in each ListBoxItem which doesn't have quite enough space to put another item on line 1. The remaining space is unused because of the HorizontalContentAlignment setting on ListBox defaulting to Left. This setting is in turn bound to by the default ListBoxItem. Setting HorizontalContentAlignment="Stretch" on your ListBox should fix that.
The outer border comes from the default setting for BorderBrush and BorderThickness. Setting BorderThickness="0" will get rid of it entirely.
There are some other default Padding settings that add some spacing in the default Styles and Templates. If you want to get more into those add a ListBox to a project in Blend and make a copy of its default Template and ItemContainerStyle and check out the XAML. Also consider using the base ItemsControl in cases where you don't need selection behavior, as it doesn't have any of these type of default settings.