Always keep column width's equal in WPF - c#

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.

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>

WPF - Columns don't hide properly when GridSplitter is moved

I'm trying to hide a column in a Grid with a GridSplitter when a button is clicked (the button sets the visibility of all items in the third column to collapsed). If I don't move the GridSplitter it works properly and the third column disappear, but if I move the GridSplitter the content disappear but the others columns don't resize to fill the empty space.
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="25"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="a" Width="*"/>
<ColumnDefinition x:Name="b" Width="3"/>
<ColumnDefinition x:Name="c" Width="Auto" MaxWidth="600"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Grid.Row="0" HorizontalAlignment="Stretch" Background="Green">
<Image Source="te/Dante.png" Height="Auto" Margin="0,128,2,71"/>
</Border>
<Button Grid.Column="0" Grid.Row="0" Width="30" Height="30" Margin="0,10,10,0" HorizontalAlignment="Right" VerticalAlignment="Top" Click="Button_Click"></Button>
<GridSplitter Width="5" Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" ResizeDirection="Columns" HorizontalAlignment="Left" Background="White" BorderBrush="Black" BorderThickness="1,0" ResizeBehavior="PreviousAndCurrent"/>
<WrapPanel x:Name="wpC" Grid.Column="2" Grid.Row="0" Grid.RowSpan="2" MinWidth="300" HorizontalAlignment="Stretch" Background="Aqua" Panel.ZIndex="-1"></WrapPanel>
</Grid>
Here is an example of my problem (gif):
How can i solve this problem? Possibly respecting MVVM pattern.
The problem is simple, you set GridSplitter ResizeBehavior="PreviousAndCurrent", but previous grid column width is * and as soon as you move splitter its width units will be changed to absolute (so it will not be able to resize when 3d column width is changed).
Simply set GridSplitter ResizeBehavior="PreviousAndNext" to solve the problem. If you do so the splitter will modify width of 3d column, but shouldn't touch first one anymore.
Btw, instead of using button and click event you can utilize ToggleButton (which IsChecked is bound to Visibility of container with content you want to hide), see this answer. Using converters with pure xaml view is better MVVM than the one with some code behind and x:Name.
Right, you have few layout problems, here is a complete solution:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border Background="Green" />
<ToggleButton x:Name="toggleButton"
Width="30"
Height="30"
Margin="0,10,10,0"
HorizontalAlignment="Right"
VerticalAlignment="Top" />
<Grid Grid.Column="1"
Visibility="{Binding IsChecked, ElementName=toggleButton, Converter={StaticResource BooleanToVisibilityConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="300"
MinWidth="300"
MaxWidth="600" />
</Grid.ColumnDefinitions>
<GridSplitter Width="5"
ResizeBehavior="CurrentAndNext" />
<WrapPanel Grid.Column="1"
Background="Aqua" />
</Grid>
</Grid>
No need for code-behind, get converter from here.
Point are: 1) put splitter inside hide-able container 2) setup grid columns to have * and fixed width (splitter doesn't work well with auto columns).
Demo:

WPF - width issue with IsSharedSizeScope "true" and three columns

Simple code:
<ItemsControl Grid.IsSharedSizeScope="True" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="firstColumn" Width="Auto"/>
<ColumnDefinition SharedSizeGroup="splitterColumn" Width="Auto"/>
<ColumnDefinition SharedSizeGroup="lastColumn" Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Key}"/>
<GridSplitter Width="5" Grid.Column="1" />
<TextBlock Text="{Binding Path=Value}" Grid.Column="2"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Problem is occured with lastColumn, width of it is not 100%. I try to set HorizontalAlignment="Stretch" for the all grids but it didn't help.
Width of lastColumn must be 100%. How to resolve this issue?
You don't need to include SharedSizeGroup on every column. In this case, if your first and second columns are sharing a size, you should be able to get your desired behaviour by omitting the property on the last column. There should always be the same amount of space for the last column, if the first two columns are sharing sizes:
<Grid Width="300" Height="30" Background="Red">
<Grid Grid.IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="firstColumn" Width="Auto"/>
<ColumnDefinition SharedSizeGroup="splitterColumn" Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox Text="1" Grid.Column="0"/>
<GridSplitter Width="5" Grid.Column="1"/>
<TextBox Text="Test" Grid.Column="2" />
</Grid>
</Grid>
Edit: This is essentially the problem encountered here: Grid.IsSharedScopeSize incompatible with * columns in WPF Grid
Further edit: You've changed to an ItemsControl now, but the same should still apply.

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

How to make a table in Silverlight?

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>

Categories