layout which allows controls to scale properly - c#

For my WPF project in C#, I have to create a menu state with a layout. Here is an image sample of how menu state should look like this.
So, my question is, which layouts should I use to make my components scalable when I resize the window and with components arranged like in prototype? I have used so far gridlayout, but I'm not sure if it is the way to go with components arranged like in prototype image.

Ideally for components that are stacked identical you use a stack panel resizing automatically depends on what the default behaviours for the panels are.
With that said horizontal stack panels auto expand only vertically and vertical stack panels expand horizontally.
Some sample code of it expanding horizontally.
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBlock Margin="5,0,5,60" HorizontalAlignment="Center">Title</TextBlock>
<Button>State</Button>
<Button>State</Button>
<Button>State</Button>
<Button>State</Button>
</StackPanel>
</Window>
If you want for them to grow both ways the easiest way is to use a grid and set them to proportional sizes.
Note the text inside the component won't auto grow. If you need that you have to use a viewbox.
How to grow/shrink a TextBlock (Font Size) to the available space in WPF?

I figured out myself how to do this. A trick is to use the properties for Horizontal and Vertical Alignment with value of Stretch and to not use width and height.
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
Example:
<Grid Background="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0">
<Viewbox>
<TextBlock>1</TextBlock>
</Viewbox>
</Button>
<Label Grid.Row="0" Grid.Column="1">
<Viewbox>
<TextBlock>2</TextBlock>
</Viewbox>
</Label>
<Button Grid.Row="0" Grid.Column="2">
<Viewbox>
<TextBlock>3</TextBlock>
</Viewbox>
</Button>
</Grid>

Related

Fixing size in xaml file

I'm newbie with Wpf application i have this interface
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Alg="clr-namespace:AS.Views.DeformableModel"
xmlns:Controls="clr-namespace:Assergs.Windows.Controls;assembly=Assergs.Windows" x:Class="AS.Window1"
Title="Window1"
>
<Grid Margin="0,0,2,0">
<Controls:RibbonPanel Header="Menu" HorizontalAlignment="Left" Margin="0,0,0,31.405" Width="213.388">
<TreeView Width="210.449" HorizontalAlignment="Left" Margin="0,0,0,-1.515"/>
</Controls:RibbonPanel>
<StatusBar Margin="0,472.595,0,0.972" VerticalAlignment="Bottom">
<Label Content="Pret" Height="41.433" Width="36.737"/>
</StatusBar>
<StackPanel Margin="213.388,0,0,31.405">
<Image Height="473.5" Source="image-interface2.jpg"/>
</StackPanel>
</Grid>
</Window>
i got as a result:
as you saw, there is many design error i need to know :
How can i display the image at the full stackpanel space ?
why the RibbonPanel controller disappeared?
How can i change my snippet to make all controller's size depending to the size of the window (image,treeview...)
I think you should to know about wpf's panels and layouts. The grid is an excellent panel and you can get almost any common layout. But for getting this you should works with columns and rows (not only with margins and vertical/horizontal orientations). The stack panel is not the best control for stretching an image: if the stackpanel's orientation is vertical the item'a height is the item's desired height, and if the orientation is horizontal, the item's width is the item's desired width, so, if you want to stretch the image you can group it inside a content control, or (if there is no more controls) do not group.
I suggest you to use a dockpanel, the dock panel alows you put the items in the locations top, right, bottom and left:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Alg="clr-namespace:AS.Views.DeformableModel"
xmlns:Controls="clr-namespace:Assergs.Windows.Controls;assembly=Assergs.Windows" x:Class="AS.Window1"
Title="Window1"
>
<DockPanel Margin="0,0,2,0">
<Controls:RibbonPanel DockPanel.Dock="Left" Header="Menu" Width="213.388">
<TreeView /> <!--The tree view will be vertican and horizontally stretch-->
</Controls:RibbonPanel>
<StatusBar DockPanel.Dock="Bottom" Height="41.433">
<Label Content="Pret" Width="36.737"/>
</StatusBar>
<Image Stretch="UniformToFill" Source="image-interface2.jpg"/> <!--The last item take all aviable space-->
</DockPanel>
</Window>
Hope this helps...
Read about Layout Containers.
http://www.codeproject.com/Articles/140613/WPF-Tutorial-Layout-Panels-Containers-Layout-Trans
In your case you may use dock panel as parent panel.
Use Grid or Border instead panels. (I have not tested this code)
<DockPanel Margin="0,0,2,0">
<Grid DockPanel.Dock="Bottom">
<Label Content="Pret" Height="41.433"/>
</Grid>
<Grid DockPanel.Dock="Left" Width="213">
<TreeView Width="210.449" HorizontalAlignment="Left"/>
</Grid>
<Grid>
<Image Source="image-interface2.jpg" Stretch="Fill"/>
</Grid>
</Grid>

How do I split a WPF window into two parts?

I want to create an app that has a listbox on the left side (I'll style it to make it look good later).
On the right side, I want to have an area where I can add controls, etc
So the question is what do I need to do to split the Window into two unequal parts
(left side approx 350 pixels wide and height should be the entire window) and the remainder is for my "canvas."
You can use a Grid:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="350" /> <!-- Or Auto -->
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListBox Grid.Column="0" />
<Canvas Grid.Column="1" />
</Grid>
Or you could use a DockPanel:
<DockPanel>
<ListBox DockPanel.Dock="Left" Width="350" />
<Canvas />
</DockPanel>
The benefit of the Grid is you have finer control over the layout and could allow the end user to dynamically resize the columns using a GridSplitter.
An alternate approach to CodeNaked's solution can be to use DockPanel where Canvas takes all space that is left automatically and you don't have to work out splits.
Of course this has the limitation of docking only to the four edges (with possibility of stacking up at edges) but I tend to prefer DockPanel when I'm making initial UI as they're rather quick and easy to setup compared to Grid setup which can get complex fairly quickly.
<DockPanel LastChildFill="True">
<ListBox DockPanel.Dock="Left" Width="350"/>
<Canvas />
</DockPanel>

New to WPF, how would I create these colored bars in my form?

I'm trying to ditch Windows Forms, and learn to use WPF professionally from now on. Pictured above is a form done in Windows Forms that I'd like to recreate in WPF.
Here is the XAML I have so far:
<Window x:Class="PizzaSoftware.UI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="297" Width="466" >
<Grid ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".20*"/>
<ColumnDefinition />
<ColumnDefinition Width=".20*"/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0">
<Backcolor?
</Rectangle>
</Grid>
</Window>
Is this even the right approach, I mean using a Rectangle. In my Windows Forms example, I used a Panel and gave it a .BackColor property.
What's the WPF way to achieve this?
Thank you.
Yes, your approach is just fine. Set the background color with the Fill property:
<Rectangle Grid.Column="0" Fill="Orange" />
<Rectangle Grid.Column="2" Fill="Orange" />
<Rectangle Grid.Column="0"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Fill="Orange" />
Set the background of the window to your orange color. Then set the background of the grid to white, set the width of the grid so that it leaves space on either side, and set the grids HorizontalAlignment to center.
<Windows ....
Background="Orange>
<Grid Background="White" HorizontalAlignment="Center" Width="300">
...
</Grid>
</Window>
I'd skip the rectangle and set the background color on the grid itself, then set colors on components within to grid.
<Grid Background="Orange">
You can set the Background property of your grid to Orange and then add your control in the middle column and Set its Background property to White. Here is a sample code:
<Window x:Class="PizzaSoftware.UI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="297" Width="466"
Height="297"
Width="466">
<Grid ShowGridLines="True" Background="Orange">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".20*"/>
<ColumnDefinition />
<ColumnDefinition Width=".20*" />
</Grid.ColumnDefinitions>
<!--Control with white background in second column-->
<GroupBox Background="White" Grid.Column="1">
<!-- Groupbox content here-->
</GroupBox>
</Grid>
</Window>

WPF: Order of stretch sizing

I'm creating a modal dialog window which contains three essential parts: a TextBlock containing instructions, a ContentControl for the dialog panel, and a ContentControl for the dialog buttons. Each of these parts are contained in a separate Grid row.
I have some specific constraints when it comes to how the dialog should be sized. The issue I'm having is with the instructions TextBlock. I want the instructions to be as wide as the ContentControl for the dialog panel. The instructions should then wrap and grow vertically as needed. Should the instructions not be able to grow vertically, then it should begin to grow horizontally.
Getting the instructions to be the width of the ContentControl and grow vertically was simple. The part I can't seem to figure out is how to get it to grow horizontally when out of vertical space. My initial thought was to create a class that extends TextBlock and override MeasureOverride. However, that method is sealed. Currently, I'm playing with the idea of have the dialog Window override MeasureOverride to calculate the available size for the instructions block.
Am I missing a much simpler way of accomplishing this? Does anyone have any better ideas than this? Messing with MeasureOverride seems like it will be a lot of work.
Here is some sample code to give you a general idea of how the dialog is laid out:
<Window
x:Class="Dialogs.DialogWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="dialogWindow"
ShowInTaskbar="False"
WindowStyle="None"
AllowsTransparency="True"
Background="Transparent"
ResizeMode="NoResize"
SizeToContent="WidthAndHeight"
WindowStartupLocation="CenterScreen">
<Border Style="{StaticResource WindowBorderStyle}" Margin="15">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock
Margin="25,5"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Text="{Binding Instructions}"
TextWrapping="Wrap"
Width="{Binding ElementName=panelContentControl, Path=ActualWidth, Mode=OneWay}"/>
<ContentControl
x:Name="panelContentControl"
Grid.Row="1"
Margin="25,5"
Content="{Binding PanelContent}"/>
<ContentControl
x:Name="buttonsContentControl"
Grid.Row="2"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Margin="25,5"
Content="{Binding ButtonsContent}"/>
</Grid>
</Border>
</Window>
It appears as if what you really want to create a new Panel or derive from an existing one which would take place of what is currently your Grid. Panel is responsible for laying out your content so you should go that way instead of messing with Window.MeasureOverride.
How exactly do you want your TextBlock to grow horizontally and why do you want this? By growing it horizontally do you want it to grow the Window too?

How to make items in a DockPanel expand to fit all available space in WPF?

I have a StackPanel containing a StackPanel and some other items. The first StackPanel has a vertical orientation, the the inner one has a horizontal orientation. The inner one has a TreeView and a ListView, I would like them to expand and fit the width of the window, which I set by the window and allow the user to change. I would also like the outer StackPanel to fit the height of the window. How do I do this?
Edit:
I've converted to using a DockPanel, and I've set the DockPanel.Dock properties correctly in each of the elements, and have disabled LastChildFill in both of the dockpanels, the layout still does not stretch.
The Code:
<Window x:Class="Clippy.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="400" Width="600" MinHeight="400" MinWidth="600" Loaded="Window_Loaded" SizeChanged="Window_SizeChanged">
<DockPanel Name="wrapperDockPanel" LastChildFill="False">
<Menu Height="22" Name="mainMenu" Width="Auto" DockPanel.Dock="Top" />
<ToolBar Height="26" Name="mainToolBar" Width="Auto" DockPanel.Dock="Top" />
<DockPanel Height="Auto" Name="contentDockPanel" DockPanel.Dock="Top" LastChildFill="False">
<TreeView Name="categoryTreeView" />
<ListView Name="clipListView" />
</DockPanel>
<StatusBar Height="23" Name="mainStatusBar" DockPanel.Dock="Top" />
</DockPanel>
</Window>
Use a DockPanel instead. StackPanel explicitly doesn't care about visible space, whereas DockPanel does all of it's size calculation based on available space.
Update:
In addition, in my experience, putting the body of the window into a View, and only having the View in the Window makes for a better Auto Size experience.
For some reason putting all of the children directly into the Window seems to not auto size very well.
Update 2:
I would remove the explicit DockPanel.Dock attribute from the element that you want to stretch (fill) the unused space.
This should do it - I set it up so that the TreeView and the ListView shared the main view 50/50; if you don't want that, set it to 'Auto' and '*' or something. Use "LastChildFill" to your advantage!
<Window x:Class="Clippy.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="400" Width="600" MinHeight="400" MinWidth="600" Loaded="Window_Loaded" SizeChanged="Window_SizeChanged">
<DockPanel LastChildFill="True">
<Menu Width="Auto" DockPanel.Dock="Top" />
<ToolBar Width="Auto" DockPanel.Dock="Top" />
<StatusBar DockPanel.Dock="Bottom" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.5*" />
<RowDefinition Height="0.5*" />
</Grid.RowDefinitions>
<TreeView Name="categoryTreeView" Grid.Row="0" />
<ListView Name="clipListView" Grid.Row="1" />
</Grid>
</DockPanel>
</Window>
Set width and height properties to "auto"

Categories