How to make a table in Silverlight? - c#

So I'd like to make a visible table, with a border around each cell and a different background color for the header. I'd like to eventually insert controls into this. For example, put a textfield inside one of the table elements, or some radio buttons, etc. Is there a control for this?
I've narrowed it down to two possibilities, but they both seem kind of "meh":
use the Grid Control - I like this but is there a way to color the border on the cell (I did not find this)
use the DataGrid Control - this control is just way too complicated for what I need.
I'm just looking for an html style table in silverlight, any ideas?

I've gotten pretty decent results with the HeaderedItemsControl in the Toolkit:
<c:HeaderedItemsControl ItemsSource="{Binding rowData}" x:Name="theTable">
<c:HeaderedItemsControl.Header>
<Border Background="HEADER BG COLOR HERE">
<Grid Width="{Binding ActualWidth, ElementName=theTable}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Field 1"/>
<TextBlock Grid.Column="1" Text="Field 2"/>
<TextBlock Grid.Column="2" Text="Field 3"/>
</Grid>
</Border>
</c:HeaderedItemsControl.Header>
<c:HeaderedItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Value1}"/>
<TextBlock Grid.Column="1" Text="{Binding Value2}"/>
<TextBlock Grid.Column="2" Text="{Binding Value3}"/>
</Grid>
</DataTemplate>
</c:HeaderedItemsControl.ItemTemplate>
</c:HeaderedItemsControl>
And of course you can style the above to your hearts content...

You can use Grid with Border element in each cell (with BorderThickness and BorderBrush\Background)
Look at this sample (with UniformGrid):
<UniformGrid Margin="10" Name="uniformGrid1">
<Border BorderThickness="1" BorderBrush="Red">
<TextBlock Text="1"></TextBlock>
</Border>
<Border BorderThickness="1" BorderBrush="Blue">
<TextBlock Text="2"></TextBlock>
</Border>
<Border BorderThickness="1" BorderBrush="Black">
<TextBlock Text="3"></TextBlock>
</Border>
<Border BorderThickness="1" BorderBrush="Yellow">
<TextBlock Text="4"></TextBlock>
</Border>
</UniformGrid>

Related

Not get autofit based on maximum length cell width to all other columns in xaml grid

I am Using treeview in XAML. Inside the treeview item am having 3 grid columns. First Column in logo which is common width. but second and third column width is based on text which is binding from backend. The second column not resizing based on max width cell that particular column based on rows values.
Please refer below screenshot
I want this file location text (Gray text) start at same position based on previous column max cell width.
Below is my code
<HierarchicalDataTemplate
<Grid Grid.IsSharedSizeScope="True" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="a"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto" SharedSizeGroup="b"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto" SharedSizeGroup="c"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Width="12" Margin="0,0,4,0" Height="auto" Source="img.png""/>
<TextBlock Grid.RowSpan="5" Grid.Column="1" Text="{Binding kmkmkmkm}" Margin="0,7,0,0" Height="20" FontSize="12">
</TextBlock>
<TextBlock Grid.Column="2" Text="{Binding loc}" Margin="10,7,0,0" Height="20" FontSize="12" Foreground="Gray">
</TextBlock>
</Grid>
</HierarchicalDataTemplate>
Suggest me on this.
After analyzing many solution, found we cannot share like this with shared size scope.
<HierarchicalDataTemplate>
<Grid Name="Grid2" HorizontalAlignment="Left" Grid.IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Width="250">
</StackPanel>
<TextBlock HorizontalAlignment="Left" Width="Auto" VerticalAlignment="Center" Grid.Column="2">
</TextBlock>
</Grid>
</HierarchicalDataTemplate>

Making a portion of a TreeViewItem wrap

I have a TreeViewItem that has multiple parts in it -- an icon, a header, and a piece of data. I'm trying to get the last part to wrap without making everything wrap, and I'm having no luck. Here's an illustration of the problem:
I've tried a few things that I've found on Stack Overflow, with no luck. There were three suggestions I found:
Put the item in a grid with a column with bound to the TreeView's actual width. This is implemented in the XAML below, but doesn't seem to help.
Disable horizontal scrolling on the TreeView with ScrollViewer.HorizontalScrollBarVisibility = "Disabled", which I also implemented in the XAML below.
Wrap what I need in a WrapPanel. I tried this, but got poor results. When I wrapped the whole TreeViewItem in one, I got wrapping that was hard to control (the whole item wraps, so all parts wrapped and it looked awful). When I wrapped just the desired TextBlock in one, I got no results at all. So I took it out.
Here's the template I have for the TreeViewItem:
<DataTemplate x:Key="BasicPropertyTemplate" DataType="{x:Type json:JProperty}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding RelativeSource={RelativeSource AncestorType=TreeView}, Path=ActualWidth}" />
</Grid.ColumnDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<ColumnDefinition Width="3" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="3" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="3" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border
Width="12"
Height="12"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="{Binding Converter={StaticResource TypeToColorConverter}, ConverterParameter='Interior'}"
BorderBrush="{Binding Converter={StaticResource TypeToColorConverter}}"
BorderThickness="1" />
<TextBlock Grid.Column="2" Text="{Binding Name, Mode=OneWay}" />
<TextBlock Grid.Column="4" Text=": " />
<TextBlock
Grid.Column="6"
Text="{Binding Value, Converter={StaticResource StringFormatConverter}, Mode=OneWay}"
TextWrapping="Wrap" />
</Grid>
</Grid>
</DataTemplate>
Here's an illustration of the layout, so you can see how the TreeViewItem is composed:
Essentially, the gray part is the icon, the green parts are just spacers between items, the blue parts are header and a colon (essentially irrelevant to what this question is about), and the red part is the actual content.
It's the red part I want to wrap.
Here's the TreeView definition:
<TreeView
x:Name="JsonRoot"
Grid.Column="0"
ItemTemplateSelector="{StaticResource TreeViewTemplateSelector}"
Loaded="JsonRoot_Loaded"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
VirtualizingStackPanel.IsVirtualizing="True" />
I feel like I'm doing something simple wrong, but I'm not sure what. Is there a way to accomplish this without just locking the TextBlock width to something arbitrary, like 200?
My investigation showed that TextBlock Wrap doesn't work with <ColumnDefinition Width="Auto"/>. So I changed last <ColumnDefinition Width="Auto"/> in DataTemplate to <ColumnDefinition Width="*"/>.
Unfortunately TreeViewItem (which is a default container for TreeView items) has <ColumnDefinition Width="Auto"/> in its Template and places our items there. I have tried to make a custom template with <ColumnDefinition Width="*"/> and it worked but code is really long. So I decided to compensate the effect by binding Grid width:
<DataTemplate x:Key="BasicPropertyTemplate" DataType="{x:Type json:JProperty}">
<Grid Width="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem}, Path=ActualWidth}" >
<Grid Margin="0,0,20,0"> <!--right margin to compensate excessive width-->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<ColumnDefinition Width="3" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="3" />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="3" />
<ColumnDefinition Width="*"/> <!--was Auto-->
</Grid.ColumnDefinitions>
<Border
Width="12"
Height="12"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="{Binding Converter={StaticResource TypeToColorConverter}, ConverterParameter='Interior'}"
BorderBrush="{Binding Converter={StaticResource TypeToColorConverter}}"
BorderThickness="1" />
<TextBlock Grid.Column="2" Text="{Binding Name, Mode=OneWay}" />
<TextBlock Grid.Column="4" Text=": " />
<TextBlock
Grid.Column="6"
Text="{Binding Value, Converter={StaticResource StringFormatConverter}, Mode=OneWay}"
TextWrapping="Wrap" />
</Grid>
</Grid>
</DataTemplate>
ScrollViewer.HorizontalScrollBarVisibility="Disabled" is important element and should be set.
Try changing the grid in DataTemplate with a DockPanel:
<DataTemplate>
<DockPanel>
<Border Width="12"
Height="12"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="{Binding Converter={StaticResource TypeToColorConverter}, ConverterParameter='Interior'}"
BorderBrush="{Binding Converter={StaticResource TypeToColorConverter}}"
BorderThickness="1" />
<TextBlock Text="{Binding Name, Mode=OneWay}" />
<TextBlock Text=": " />
<TextBlock Text="{Binding Value, Converter={StaticResource StringFormatConverter}, Mode=OneWay}"
TextWrapping="Wrap" />
</DockPanel>
</DataTemplate>

Always keep column width's equal in WPF

I current have a WPF application that contains a ListBox of Grid items.
These grids have 2 columns each and the first column contains text and the second one contains an ellipse.
My issue is that I currently have both ColumnDefinition set to have width of .5* so they each take 50% of the total width. However, this doesn't work when the text is too long or else it pushes the ellipse in the second column out of line with the rest of the ellipses in the list (looking vertically from top to bottom).
Basically this is what I get:
What I would like to happen is have all of the elipses in-line no matter how long the text in the first column is.
I've tried placing the first column's text inside of a ViewBox to auto-size it but that doesn't seem to work either.
Here is the full XAML for the DataTemplate:
<Grid x:Name="MainTermServListGrid">
<Grid.RowDefinitions>
<RowDefinition x:Name="MainTermServMainRow"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding TServer}" FontSize="15" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Grid x:Name="OldPathGrid" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".5*"/>
<ColumnDefinition Width=".5*"/>
</Grid.ColumnDefinitions>
<Viewbox Grid.Column="0" Stretch="Uniform">
<TextBlock Grid.Column="0">
<Run Text="Path: "/>
<Run Text="{Binding OldPath}"/>
</TextBlock>
</Viewbox>
<Ellipse Grid.Column="1" HorizontalAlignment="Center" Width="{Binding ElementName=MainTermServListGrid, Path=ActualHeight}" Fill="{Binding IsOldPathValid, Converter={StaticResource ValPthToBgClr}}"/>
</Grid>
<Grid x:Name="NewPathGrid" Grid.Column="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".5*"/>
<ColumnDefinition Width=".5*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0">
<Run Text="Path: "/>
<Run Text="{Binding NewPath}"/>
</TextBlock>
<Ellipse Grid.Column="1" Width="{Binding ElementName=MainTermServListGrid, Path=ActualHeight}" Fill="{Binding IsNewPathValid, Converter={StaticResource ValPthToBgClr}}"/>
</Grid>
</Grid>
You should take a look at SharedSizeGroup
Essentially:
<ItemsControl ItemsSource="{Binding SomeItems}"
Grid.IsSharedSizeScope="True">
<ItemsControl.ItemTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="ColA" Width=".5*" />
</Grid.ColumnDefinitions>
</Grid>
</ItemsControl.ItemTemplate>
</ItemsControl>
Using the SharedSizeScope and SharedSizeGroup, you can ensure columns / rows are the same size across different grids within the same containing scope
NOTE: It doesn't have to be an ItemsControl any container using the attached property Grid.IsSharedSizeScope will ensure that grids contained within will pay attention.

Cannot get TextBlock to word wrap inside a ListBox

I am having trouble getting the text in a TextBlock to wrap. The TextBlock is inside a Grid, which is part of a ListBoxItem template. Below is my XAML:
<ListBox Grid.Row="2" ScrollViewer.HorizontalScrollBarVisibility="Disabled" HorizontalAlignment="Center" VerticalAlignment="Top" Height="600" Width="600" Name="lb_TestResults" ItemsSource="{Binding Test}" Margin="5,5,5,5">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="DarkGray" BorderThickness="1" Padding="4">
<Grid Width="auto">
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock Name="tb_nameLabel" Margin ="0, 0, 3, 0" FontSize="15" FontFamily="Verdana" Grid.Row="0" Grid.Column="0"><Bold>Test: </Bold></TextBlock>
<TextBlock Name="tb_Name" Text="{Binding Name}" FontSize="15" FontFamily="Verdana" Grid.Row="0" Grid.Column="1"></TextBlock>
<TextBlock Name="tb_descLabel" Margin="0, 0, 3, 0" TextWrapping="Wrap" Grid.Row="1" Grid.Column="0"><Bold>Description: </Bold></TextBlock>
<TextBlock Name="tb_Description" Text="{Binding Description}" Grid.Row="1" Grid.Column="1" ></TextBlock>
<TextBlock Name="tb_statusLabel" Margin="0, 0, 3, 0" Grid.Row="2" Grid.Column="0"><Bold>Status: </Bold></TextBlock>
<TextBlock Name="tb_Status" Text="{Binding Status}" Grid.Row="2" Grid.Column="1"></TextBlock>
<TextBlock Name="tb_resultLabel" Margin="0, 0, 3, 0" Grid.Row="3" Grid.Column="0"><Bold>Result: </Bold></TextBlock>
<TextBlock Name="tb_Result" Text="{Binding Result}" Grid.Row="3" Grid.Column="1"></TextBlock>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I originally had the TextBlocks inside StackPanels, but reading various other questions on this topic such as this, I decided to change it to a Grid. I only need the TextBlock tb_Description to word wrap. Right now the output looks like this:
As you can see the text is not wrapping.
I have tried setting the width explicitly on the TextBlocks, the Grid columns, and the ListBox, but nothing has helped so far. I also disabled the horizontal scrollbar, the scrollbar is gone now but the text is still trailing off the edge. Any ideas?
The problem is not with the ListBox but with the Grid you are using to align text blocks. Both columns are set to Auto which results in Grid allowing columns to occupy all space their content requests for.
You need to set Width of the second ColumnDefinition to *:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
Hi you must set the 2nd column to * so it stretches and you have swapped the TextBlock that should wrap, just a "typo" :)
Change
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<!-- And these here you have set the wrong textblock to wrap =) -->
<TextBlock Name="tb_descLabel" Margin="0, 0, 3, 0" TextWrapping="Wrap" Grid.Row="1" Grid.Column="0"><Bold>Description: </Bold></TextBlock>
<TextBlock Name="tb_Description" Text="{Binding Description}" Grid.Row="1" Grid.Column="1" ></TextBlock>
To
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- ..... -->
<TextBlock Name="tb_descLabel" Margin="0, 0, 3, 0" Grid.Row="1" Grid.Column="0"><Bold>Description: </Bold></TextBlock>
<TextBlock Name="tb_Description" Text="{Binding Description}" Grid.Row="1" Grid.Column="1" TextWrapping="Wrap"></TextBlock>
Result
Cheers!

How to generically repeat the style of a listboxitem in Silverlight / Windows phone 7

I have a ListBox and I need to repeat the styles to be the same for all the listbox items. Only the placeholders are going to change. For example, the following listbox item has three elements - An Image, a header text and a description text. I have styled it. Now I need to apply the same style for the listboxitems that I follow. Currently I am doing a copy paste for all the items which is not the right way.
I can do this via ListBoxTemplate and DataTemplate but I need to write the code in .cs file which I don't want to. Help me how to achieve the template effect ?
Here is the code for the above listboxitem.
<ListBoxItem>
<Grid Height="80">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="/Images/dark/appbar.magnify.png"/>
<StackPanel Grid.Column="1">
<TextBlock Text="Item heading" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="item description" TextWrapping="Wrap" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</Grid>
</ListBoxItem>
I need place holder for the image, header text and content text in all the listboxitems that I add. How to achieve this?
This is how you can achieve it :
<Page.Resources>
<DataTemplate x:Key="ListTemplate">
<Grid Height="80">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="/Images/dark/appbar.magnify.png"/>
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding ItemHeading}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding ItemDescription}" TextWrapping="Wrap" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</Grid>
</DataTemplate>
</Page.Resources>
<Grid>
<ListBox ItemTemplate="{StaticResource ListTemplate}" ItemsSource="{Binding YourList}">
</ListBox>
</Grid>
You can put the Resource in App.XAML so it can be accessed by all pages, and you can use it on all ListBoxes in your Application. Note that elements in your YourList should have ItemHeader and ItemDescription properties
You can create a dataitem template like this
<DataTemplate x:Key="DataTemplate1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{Binding Image}" Width="10" Height="10"/>
<TextBlock Grid.Column="1" Text="{Binding ID}"/>
<TextBlock Grid.Column="2" Text="{Binding content}"/>
</Grid>
</DataTemplate>
and then bind this data template to the list and then bind the item to the list.. :)
u can bind collection of list with class
You can create a class with three variables image,id and content so that u can make a list of that class and bind to the list
Create/Use a ListItem ItemTemplate

Categories