Workaround for Grid.SharedSizeGroup in Silverlight - silverlight

There is no Grid.SharedSizeGroup in Silverlight 4. What is your workaround for this issue?
For example: I have a DataTemplate for ListBox.ItemTemplate consisting of a grid with two columns and I'd like to have the same width for both columns and the first column needs to have auto width.

Vote for this feature here:
http://dotnet.uservoice.com/forums/4325-silverlight-feature-suggestions/suggestions/1454947-sharedsizegroup
and also here:
http://connectppe.microsoft.com/VisualStudio/feedback/details/518461/sharedsizegroup-should-be-available-in-silverlight

SharedSize Grid with Silverlight - haven't tested it but looks usable.

Shared sizing is best implemented using element property bindings in Silverlight. Just make all your shared sized elements bind to the width/height of another.
EDIT:
I put a quick example of what I mean together. I'm not sure what you mean by using star sizing when you said in the question you want auto sizing -
<Grid Height="400"
Width="600"
Background="Gray">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button x:Name="parent"
Content="CHANGE ME TO ADJUST THE COLUMN SIZE"
Grid.Column="0"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Background="Red" />
<Button Width="{Binding ActualWidth, ElementName=parent}"
Grid.Column="1"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Background="Blue" />
<Button Width="{Binding ActualWidth, ElementName=parent}"
Grid.Column="2"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Background="Yellow" />
</Grid>
HTH

Related

Width of Textbox, which placed in grid column, extends when inserting long text

When I put a Textbox in a grid column like below
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MinWidth="115"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="90"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="hello"/>
<TextBox Grid.Column="1" />
<Button Grid.Column="2" Content="push me"/>
</Grid>
</StackPanel>
I get proper result, i.e. textbox width is get from parent grid
But when I type a long text, the textbox starts exceeding its column and it stops extending after several extra letters
To .Net 4.6.2, I get same result but changing to .Net 4.7.2 the problem is solved i.e. the textbox width is not changing.
My software is compiled .Net 4.0, is there a solution to solve this for lower .net than 4.7.2?
Tried Pavel's first idea: removing stackpanel and adding another grid row in, still not working in .net 4.6.2
Tried Pavel's second idea: making the width of first column "Auto" instead of "1*". This works, the textbox doesn't extend (.net 4.6.2), however I really wanted the first and second column be responsive to resize.
You can solve this be removing the StackPanel and adding RowDefinition to Grid. You can also set TextWrapping="Wrap" for TextBox for wrapping a long text
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="90"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Text="hello" MinWidth="115"/>
<TextBox Grid.Column="1" TextWrapping="Wrap"/>
<Button Grid.Column="2" Content="push me"/>
</Grid>
StackPanel Y dimension is constrained to content, it will be automatically expanded to its content, more details can be found at panels overview
To me this is a bug that Textbox text size can change its parent width (grid width). This is happening in VS2019 .Net 4->4.6.2 but not in and after .Net 4.7.2.
For anybody faces this problem, I found below workaround by defining an invisible grid which contains textblocks. I get the widths of columns and give them to controls placed in a StackPanel.
<some container>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" MinWidth="115"/>
<ColumnDefinition Width="3*" />
<ColumnDefinition MinWidth="90"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0"/>
</Grid.RowDefinitions>
<TextBlock x:Name="C0" Grid.Column="0" />
<TextBlock x:Name="C1" Grid.Column="1" Margin="5"/>
<TextBlock x:Name="C2" Grid.Column="2" />
</Grid>
<StackPanel Orientation="Horizontal">
<TextBlock Width="{Binding ElementName=C0, Path=ActualWidth }" Text="hello" />
<TextBox Width="{Binding ElementName=C1, Path=ActualWidth }" Margin="5" />
<Button Width="{Binding ElementName=C2, Path=ActualWidth }" Content="push me"/>
</StackPanel>
</some container>
The margin should be the same for column in grid and control in StackPanel (see second column).

WPF Element Binding With Dynamically Generated UI Elements

I have a page in which I have a grid with 2 columns, one accommodating 80* width and the other accommodating 20*. Beneath the grid is a stack panel to which I load UI elements (child stack panels) at runtime.
My objective is to bind the widths of the stackpanels to the columns of the grid. This works perfectly and the stackpenels resize if the dynamic content is mocked to be static in the design view. But when the application is run, the bindings fail and the widths are not bound.
Is there any way to refresh the bindings so that I can notify the stackpanels to refer the widths of the grid and configure its's size?
Updated:
This is what my XAML looks like:
<Page x:Class="WPFTestApp.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Page1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid x:Name="resizeGrid"
Grid.Column="0" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="leftColumn"
Width="80*" />
<ColumnDefinition x:Name="rightColumn"
Width="20*" />
</Grid.ColumnDefinitions>
</Grid>
<StackPanel x:Name="contentPanel"
Grid.Column="0" Grid.Row="0" >
<!-- Dynamic StackPanels are added here -->
</StackPanel>
</Grid>
</Page>
In my code, I create StackPanel elements and add it to the contentPanel by saying:
contentPanel.Children.Add(...);
Unfortunately, I HAVE to use StackPanels here. :-(
The markup of a dynamically created StackPanel element is as follows (note that I use a Binding to the grid already in the XAML):
<StackPanel x:Name="element01"
Orientation="Horizontal"
Width="{Binding ElementName=resizeGrid, Path=ActualWidth}" >
<StackPanel x:Name="leftPanel"
Orientation="Vertical"
Width="{Binding ElementName=leftColumn, Path=ActualWidth}">
<!-- Content goes here -->
</StackPanel>
<StackPanel x:Name="rightPanel"
Orientation="Vertical"
Width="{Binding ElementName=rightColumn, Path=ActualWidth}">
<!-- Content goes here -->
</StackPanel>
</StackPanel>
The XAML code for my dynamic StackPanel elements are generated through an XSLT transformation
Note the xmlns:x namespace dynamic StackPanel. This also has to be done because of it being generated through XSLT
As far as I know setting the Width of a StackPanel with Orientation="Horizontal" will have no effect. The size of a StackPanel does not exceed the size of its content in its oriented direction.
Why do you "HAVE" to use StackPanels here? You almost certainly want DockPanels, given your objective. You won't have to bind or set anything, because the DockPanel will fill the cell automatically.
Try binding the ActualWidth instead of Width.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid x:Name="resizeGrid"
Grid.Column="0" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="leftColumn"
Width="{Binding ElementName=contentPanel, Path=ActualWidth}" />
<ColumnDefinition x:Name="rightColumn"
Width="*" />
</Grid.ColumnDefinitions>
</Grid>
<StackPanel x:Name="contentPanel"
Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" >
<StackPanel Background="Yellow" Width="100" Height="25" />
<StackPanel Background="Green" Width="120" Height="25" />
<StackPanel Background="Red" Width="140" Height="25" />
<TextBlock Background="Gray" Text="{Binding ElementName=contentPanel, Path=ActualWidth}" />
</StackPanel>
</Grid>
The following changes I have done above:
1) Set the leftColumn to the ActualWidth of the contentPanel
2) Set the rightColumn to *
3) contentPanel HorizontalAlignment should be changed other then Stretch. Here I have changed it to Left
HTH
I found a solution for this issue. (Sorry for the late response)
What I did was, I cut and pasted the "resizeGrid" Grid control into the "contentPanel" Stackpanel.
As I mentioned above, the contents within the contentPanel are generated through an XSLT transformation and this surely creates a namespace reference issue. I noticed "element not found..." message in the Output window whenever this Window is loaded - this proved me right.
Inserting the "resizeGrid" into the "contentPanel" helped because then both the controls are within the same namespace and can be referenced for a PropertyBinding using "ElementName" attribute.
Thank you for your support! :-)

Is there a better way than a grid to line up controls in WPF?

I am using a grid by the definition of appropriateness defined in this question Grid vs Stackpanel. However when working with grids you have to define the controls position inside them explicitly in the grid. This becomes a pain when having to reorder controls or when adding a new control to the grid. With the code provided as an example, is there a way to get the rows and columns for the text and text boxes to line up while being easy to modify or expand later?
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="7*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="Value One:" Grid.Row="0" Grid.Column="0"/>
<TextBox x:Name="TextBoxOne" Grid.Row="0" Grid.Column="1"/>
<TextBlock Text="Value Two:" Grid.Row="1" Grid.Column="0"/>
<TextBox x:Name="TextBoxTwo" Grid.Row="1" Grid.Column="1"/>
<TextBlock Text="Value Three:" Grid.Row="2" Grid.Column="0"/>
<TextBox x:Name="TextBoxThree" Grid.Row="2" Grid.Column="1"/>
</Grid>
I wrote a custom control I use that makes it extremely easy to do this, but before I created it I generally used this sort of thing:
<ControlTemplate x:Key="ColumnsTemplate" TargetType="HeaderedContentControl">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="7*" />
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0" ContentSource="Header" />
<ContentPresenter Grid.Column="1" />
</Grid>
</ControlTemplate>
<ItemsControl ... ItemTemplate="{StaticResource ColumnsTemplate}">
<HeaderedContentControl Header="Value One:">
<TextBox x:Name="TextBoxOne" />
</HeaderedContentControl>
<HeaderedContentControl Header="Value Two:">
<TextBox x:Name="TextBoxTwo" />
</HeaderedContentControl>
...
</ItemsControl>
This allows easy add/remove of items from the ItemsControl, or better yet, data binding.
If you prefer auto-sizing on the grid rather than star sizing (3* and 7*) you can use a shared sizing scope by setting IsSharedSizeScope on the ItemsControl and SharedSizeGroup on the first ColumnDefinition.
Another option is GridView, but I find it more difficult to use for this purpose.

WPF TextBlock Padding is cutting off text

I have a TextBlock in a Grid with its Padding attribute set to 5. Sometimes the last character is cut off, depending on what string the Text property is set to.
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SomeClass">
<ScrollViewer Padding="5" VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label
Grid.Row="0" Grid.Column="0"
Content="SomeLabel"
HorizontalAlignment="Right"
HorizontalContentAlignment="Right"
VerticalAlignment="Center" />
<TextBlock
Grid.Row="0" Grid.Column="1"
HorizontalAlignment="Left"
Padding="5"
Text="0x0F"
TextWrapping="Wrap"
VerticalAlignment="Top" />
</Grid>
</ScrollViewer>
</UserControl>
When the Text is set to 0x0F the F is not visible. When it is set to 0xAB the string displays just fine. Setting the Padding to 0 also makes the string display just fine.
What you describe is obviously a layout bug in WPF (probably in the TextBlock). Whether or not the last letter is wrapped (and cut off) seems to depends on the actual width of the string and the size of the last letter in respect to the size of the padding.
I suggest you report the bug here.
To work around this issue you can use the following code (just put a border around you textblock and set the padding there instead):
<Border Padding="5" Grid.Row="0" Grid.Column="1">
<TextBlock HorizontalAlignment="Left"
Text="0x0F" TextWrapping="Wrap"
VerticalAlignment="Top" />
</Border>
Make the column of the grid that contains textblock auto size like this
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.COlumn="0" Text="{Binding Path=SomeViewModelProperty}" />
</Grid>
If you set the height on the TextBlock to 100, does the F then get wrapped?
Just increase the Height of the ComboBoxItem , it should solve the problem.

Silverlight activity control - messing up width and height?

I'm struggling with Silverlights' activity control. I placed a grid inside the activity control and no matter whether it shows "Loading..." or not, the grid doesn't stretch anymore, only the min-values are applied.
After removing the activity-control everything works fine, againg - but I need to use the ctrl.
Did I do something wrong?
Best regards,
rwh
Code:
<Grid x:Name="LayoutRoot" Style="{StaticResource DetailPageLayoutRoot}">
<activity:Activity IsActive="{Binding IsBusy}">
<Grid ShowGridLines="True" MinWidth="200" MinHeight="200" Background="Bisque" >
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="50" Width="0.2*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition MinWidth="50" Width="0.8*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Margin="1" Background="Beige">
...
</StackPanel>
<controls:GridSplitter Grid.Column="1" VerticalAlignment="Stretch" HorizontalAlignment="Center" Margin="1" Width="4" MinWidth="4" MaxWidth="4"/>
<StackPanel Grid.Column="2" Margin="1" Background="AliceBlue">
...
</StackPanel>
</Grid>
</activity:Activity>
</Grid>
Update:
This control has now(Nov 2009) been incorporated into the Silverlight toolkit. Its been renamed the BusyIndicator. Get it here.
Original Answer:
The latest version of the control fixes this problem.
Download it here: http://www.davidpoll.com/2009/09/14/update-2-displaying-background-activity-in-a-silverlight-ria-application/
I am having the same problem. I think it might be something wrong with the control.
You could set the minwidth/height programmatically.
So innerGrid.minWidth = innerGrid.Parent.Parent.actualwidth;
Not sure if that will work though.

Resources