WPF Square auto-size to parent container - wpf

I have a UniformGrid object in my WPF project that has 2 rows and 3 cols and its width and height are set to auto (with both alignments set to Stretch).
This grid will hold 6 squares that I want to fill as much of their cell as possible and be centered horizontally and vertically.
What do I need to be added to allow for the squares to increase/decrease their length/width based on the dynamic size of the parent? I.E., when the window is resized.
Here is my xaml so far:
<UniformGrid Rows="2" Columns="3">
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100"/>
</UniformGrid>
Edit:
And the Rectangle objects need to remain square.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Grid>
<UniformGrid Rows="2" Columns="3">
<Viewbox Stretch="Uniform"><Rectangle Height="100" Width="100" Fill="#FFF4F4F5" Stroke="Black" /></Viewbox>
<Viewbox Stretch="Uniform"><Rectangle Height="100" Width="100" Fill="#FFF4F4F5" Stroke="Black" /></Viewbox>
<Viewbox Stretch="Uniform"><Rectangle Height="100" Width="100" Fill="#FFF4F4F5" Stroke="Black" /></Viewbox>
<Viewbox Stretch="Uniform"><Rectangle Height="100" Width="100" Fill="#FFF4F4F5" Stroke="Black" /></Viewbox>
<Viewbox Stretch="Uniform"><Rectangle Height="100" Width="100" Fill="#FFF4F4F5" Stroke="Black" /></Viewbox>
<Viewbox Stretch="Uniform"><Rectangle Height="100" Width="100" Fill="#FFF4F4F5" Stroke="Black" /></Viewbox>
</UniformGrid>
</Grid>
</Page>

You could do this:
<UniformGrid.Resources>
<Style TargetType="Rectangle">
<Setter Property="Width"
Value="{Binding RelativeSource={RelativeSource Mode=Self},Path=ActualHeight}" />
</Style>
</UniformGrid.Resources>
Or you could bind the Height to the ActualWidth.
Unfortunately this will not keep them stretched to the maximum.

If you remove the height and width properties it will do just that.

Related

Margin in wrappanel

I'm using WPF's wrappanel. the problem is that in the right side of it there's an empty space that I would like to reduce and I don't know how.
in the pic below you can see the right against the left side margin, I would like them both to be like the left one.
This is my XAML:
<Grid x:Name="root">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="263*" />
<ColumnDefinition Width="240*" />
</Grid.ColumnDefinitions>
<Rectangle Fill="LightBlue"/>
<WrapPanel >
<Rectangle Margin="10" Fill="Red" Width="40" Height="40"></Rectangle>
<Rectangle Margin="10" Fill="Red" Width="40" Height="40"></Rectangle>
<Rectangle Margin="10" Fill="Red" Width="40" Height="40"></Rectangle>
<Rectangle Margin="10" Fill="Red" Width="40" Height="40"></Rectangle>
<Rectangle Margin="10" Fill="Red" Width="40" Height="40"></Rectangle>
<Rectangle Margin="10" Fill="Red" Width="40" Height="40"></Rectangle>
</WrapPanel>
</Grid>
It looks like you forgot to center the WrapPanel in the Column. Like this:
<Grid x:Name="root">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="263*" />
<ColumnDefinition Width="240*" />
</Grid.ColumnDefinitions>
<Rectangle Fill="LightBlue"/>
<WrapPanel HorizontalAlignment="Center">
<Rectangle Margin="10" Fill="Red" Width="40" Height="40"></Rectangle>
<Rectangle Margin="10" Fill="Red" Width="40" Height="40"></Rectangle>
<Rectangle Margin="10" Fill="Red" Width="40" Height="40"></Rectangle>
<Rectangle Margin="10" Fill="Red" Width="40" Height="40"></Rectangle>
<Rectangle Margin="10" Fill="Red" Width="40" Height="40"></Rectangle>
<Rectangle Margin="10" Fill="Red" Width="40" Height="40"></Rectangle>
</WrapPanel>
</Grid>
You're getting the big space at the end because it can only fit so many squares in the space you've assigned it. It can't quite fit the last square in to the first line so it wraps it. That chunk of space on the right is just the extra "dead" space.
The other thing you can do with a WrapPanel is specify how big the item is going to be. You'll see I've used the ItemHeight and ItemWidth properties, this gives me more control over how it is sized.
<Grid x:Name="LayoutRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="263*" />
<ColumnDefinition Width="280*" />
</Grid.ColumnDefinitions>
<Rectangle Fill="LightBlue"/>
<WrapPanel ItemHeight="60" ItemWidth="60" >
<Rectangle Margin="5" Fill="Red" Width="60" Height="60"></Rectangle>
<Rectangle Margin="5" Fill="Red" Width="60" Height="60"></Rectangle>
<Rectangle Margin="5" Fill="Red" Width="60" Height="60"></Rectangle>
<Rectangle Margin="5" Fill="Red" Width="60" Height="60"></Rectangle>
<Rectangle Margin="5" Fill="Red" Width="60" Height="60"></Rectangle>
<Rectangle Margin="5" Fill="Red" Width="60" Height="60"></Rectangle>
</WrapPanel>
</Grid>

Vertical aligning content of PathListBox

I have a control containing a PathListBox from Blend SDK (see XAML below). The items inside are of identical width and various height. Currently, the midpoint of the items follow the arc's path (see the picture) i.e. they are clearly vertically arranged 'center'. However, I would like the items 'top' vertically aligned, so their top follows the arc's path. How can I do that?
<Grid x:Name="LayoutRoot">
<ec:PathListBox Margin="160,290,-30,-250">
<ec:PathListBox.LayoutPaths>
<ec:LayoutPath SourceElement="{Binding ElementName=arc}"
Padding="-25" FillBehavior="NoOverlap"
Distribution="Even" Span="0.5"/>
</ec:PathListBox.LayoutPaths>
<Rectangle Fill="#FFF4F4F5" Height="103" Width="100"/>
<Rectangle Fill="#FFF4F4F5" Height="120" Width="100"/>
<Rectangle Fill="#FFF4F4F5" Height="140" Width="100"/>
<Rectangle Fill="#FFF4F4F5" Height="265" Width="100"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Width="100"/>
<Rectangle Fill="#FFF4F4F5" Height="265" Width="100"/>
</ec:PathListBox>
<ed:Arc x:Name="arc"
ArcThickness="10" ArcThicknessUnit="Pixel" Margin="160,290,-30,-250"
Stretch="None" Stroke="Transparent" StartAngle="-7"
RenderTransformOrigin="0.5,0.5" StrokeThickness="3"
Opacity="0.155" Fill="LightGray">
<ed:Arc.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleY="1" ScaleX="-1"/>
<SkewTransform AngleY="-17" AngleX="-16"/>
<RotateTransform Angle="0"/>
<TranslateTransform/>
</TransformGroup>
</ed:Arc.RenderTransform>
</ed:Arc>
</Grid>
Just change margins of your rects:
...
<Rectangle Fill="Green" Height="103" Width="100" Margin="0,130,0,0"/>
<Rectangle Fill="Green" Height="120" Width="100" Margin="0,120,0,0"/>
<Rectangle Fill="Green" Height="140" Width="100" Margin="0,140,0,0"/>
<Rectangle Fill="Green" Height="265" Width="100" Margin="0,265,0,0"/>
<Rectangle Fill="Green" Height="100" Width="100" Margin="0,100,0,0"/>
<Rectangle Fill="Green" Height="265" Width="100" Margin="0,265,0,0"/>
...
I'm after trying it myself on Blend4 and it works.

How to leave margin between elements in the stack panel

I use the stack panel. It looks like every elements inside is stacking tightly. How to leave some margin between them.
Easiest way is to give each item it's own Margin
<StackPanel Grid.Row="1" Orientation="Horizontal">
<Rectangle Fill="White" Stroke="Black" Width="100" Height="35" StrokeThickness="5" Margin="5,0,0,0"/>
<Rectangle Fill="White" Stroke="Black" StrokeThickness="5" Width="100" Height="35" Margin="5,0,0,0"/>
<Rectangle Fill="White" Stroke="Black" Width="100" Height="35" Margin="5,0,0,0" StrokeThickness="5"/>
</StackPanel>

WPF/XAML Application Crashes when Blend not installed - Event Logs Attached

Below is the full XAML for the WPF application, no codebehind. On computers that have Expression Blend 4 installed, the following application works. However, on machines that do not have Blend, the application crashes. This is extremely simplistic, but it appears that the [i:Interaction.Behaviors] portion is what is causing the issue, which is a behavior from Blend that creates a smooth animation.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
x:Class="WpfApplication12.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Grid x:Name="LayoutRoot">
<WrapPanel>
<i:Interaction.Behaviors>
<ei:FluidMoveBehavior AppliesTo="Children"/>
</i:Interaction.Behaviors>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Margin="10"/>
</WrapPanel>
</Grid>
You should ship System.Windows.Interactivity.dll with your application. Go to properties of that DLL in the references of you project and set Copy Local property to True. After that this assembly will be copied to the output folder of the project.
You need to include System.Windows.Interactivity.dll which is located at (Blend 3 pathing) ...Program Files\Microsoft SDKs\Expression\Blend 3\Interactivity\Libraries\WPF
That file is redistributable as defined by (Blend 3 pathing) ...Program Files\Microsoft SDKs\Expression\Blend 3\Redist.en.txt

ScrollViewer not scrolling in WPF

I am using a scrollviewer control around my stack panel which contains an ItemsControl. When there are many items in the ItemsControl it is suppose to scroll but for some reason it just cuts of the items. Here is the code:
<StackPanel>
<ScrollViewer CanContentScroll="True" VerticalScrollBarVisibility="Visible">
<ItemsControl Name="icEvents" Width="Auto" Height="100" Background="AliceBlue"
ItemsSource="{Binding Path=EventSources}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="Source:"/>
<TextBlock Text="{Binding Path=Source}" />
<TextBlock Text="Original Source:"/>
<TextBlock Text="{Binding Path=OriginalSource}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</StackPanel>
Try a grid around your ScrollViwer instead of the StackPanel. I think StackPanel will provide as much height as the internal content wants, so here the Scrollviwer doesn't work properly since its height is not get restricted by its parent control.
You can understand the issue from the example below.
<StackPanel>
<ScrollViewer>
<ItemsControl >
<Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
<Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
<Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
<Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
<Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
</ItemsControl>
</ScrollViewer>
</StackPanel>
Above code is similar to yours and it doesn't give you scrollbars. But see the below code in which I changed only the StackPanel to a Grid(Any panel which respects the size of its children based on panels size but stackpanel doesn't)
<Grid>
<ScrollViewer>
<ItemsControl >
<Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
<Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
<Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
<Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
<Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
</ItemsControl>
</ScrollViewer>
</Grid>
UPDATE : But if you really need to use StackPanel then you might need to set the size for your ScrollViwer to get the Content scroll
You must fix the Height of the Scrollviewer, but can easily bind to the StackPanel ActualHeight:
(tested code)
<StackPanel Name="mypanel">
<ScrollViewer Height="{Binding ElementName=mypanel, Path=ActualHeight}">
<ItemsControl>
<Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" Width="200"/>
<Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" />
<Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" Width="200"/>
<Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" />
<Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" />
</ItemsControl>
</ScrollViewer>
</StackPanel>
Or better yet, if you can't change the name of the StackPanel:
<StackPanel>
<ScrollViewer Height="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type StackPanel}}, Path=ActualHeight}">
<ItemsControl>
<Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" Width="200"/>
<Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" />
<Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" Width="200"/>
<Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" />
<Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" />
</ItemsControl>
</ScrollViewer>
</StackPanel>
It is a "You first" problem, the StackPanel ask the ScrollViewer for the Height and the ScrollViewer ask the StackPanel for the max Height it can be.
The ItemsControl should contain the ScrollViewer, not the other way around. All that the ScrollViewer knows about is the ItemsControl itself in your case - it doesn't know about the inner items.
Try something like this:
<ItemsControl Name="icEvents" Width="Auto" Height="100"
Background="AliceBlue"
ItemsSource="{Binding Path=EventSources}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="Source:"/>
<TextBlock Text="{Binding Path=Source}" />
<TextBlock Text="Original Source:"/>
<TextBlock Text="{Binding Path=OriginalSource}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Template>
<ControlTemplate TargetType="ItemsControl">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ItemsPresenter Margin="5" />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
The Scroll needs to be the parent of the resizing child so, put the resizing control(in this instance the stack panel) inside it.
<ScrollViewer>
<StackPanel>
<Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
<Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
<Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
<Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
<Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
</StackPanel>
I had a problem whereby I showed an ItemsControl in a Grid and in order to see the scrollbars, I had to give this Grid cell *-sized height.
However, this meant that the ItemsControl always filled the cell even when there were only a few values.
I wanted the ItemsControl to be only big enough to show what it had but if it had too many items then I wanted it to scroll. In order words I wanted this to work only any size monitor.
This code in the Loaded event worked for me:
Size x = new Size(double.PositiveInfinity, double.PositiveInfinity);
myItemscontrol.Measure(x);

Resources