Absolutely centered content inside a WPF layout panel - wpf

I need to find a way of absolutely centering the content of a LayoutPanel in WPF. I have two textblock elements which must render at the vertical and horizontal center of the panel without relying on absolute heights and widths.
This is something i can do quite easily with a single element since any ContentControl can have it's verticalContentAlignment property set but then you only have a single child element to play with and i'm back to square one.
Any help would be massively appreciated.

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid VerticalAlignment="Center">
<StackPanel HorizontalAlignment="Center">
<TextBlock>First</TextBlock>
<TextBlock>and the second</TextBlock>
</StackPanel>
</Grid>
</Window>
You could also write your own Panel subclass that does this automatically.

Fixed it as i asked it!
What i needed to do was place a StackPanel inside a ContentControl and set the StackPanels VerticalAlignment to Center. Seems obvious now!

Related

WPF cannot dock control in a dock panel, canvas seems to instead get centered

When using the xaml markup
<Window x:Class="Foo.Bar.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="400" Width="400">
<DockPanel LastChildFill="True">
<Canvas DockPanel.Dock="Right" Width="100" />
</DockPanel>
</Window>
...it seems like the canvas does not get docked to the right.
Why?
Instead it becomes centered.
You have LastChildFill set to true. As your DockPanel only has one child, it is also the last child, so it is being overridden to Fill. The reason it is getting centered is that the Width has been explicitly set to 100. Since it can't fill with that override, it does the best it can, and centers it.
Simply removing LastChildFill will not fix the issue, as the default value is true. To fix this, you will have to explicitly set LastChildFill to false.
The reason for these default settings is that DockPanel is usually used to house multiple child controls, where the children docked to different sides are listed first, and the final child takes up the remaining area. Using it with only a single child is fairly unusual.

Xaml - Vertical scrollbar in stackpanel

I have creating a wpf application and in my settings panel I have tons of UI elements. The problem is that when I resize the window some of these elements are not visible anymore. Is there any way to add a simple vertical scrollbar?
I have tried this below and add my content into it :
<ScrollViewer VerticalScrollBarVisibility="Auto">
<Grid>
<StackPanel>
//Content
</StackPanel>
</Grid>
</ScrollViewer>
I'm not sure if I put the ScrollViewer to the right Place but I got this error :
The member resources is not recognized or is not accessible
and for this error I have tried to replace the Page.Resources with Window.Resources but it did not help.
Anyways how could I get my vertical scrollbar working? Any helps?
Problem solved by removing the Width and Height properties from the Page.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="800" Width="1400"
WindowTitle="ScrollViewer Sample">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<Grid>
<StackPanel>
//Content
</StackPanel>
</Grid>
</ScrollViewer>
</Page>
You should get rid of the StackPanel. A StackPanel measures its children with an infinite space and therefore it doesn't work very well with scroll bars:
Horizontal scroll for stackpanel doesn't work

Why AdornerLayers are always the top most layers? Is there a way to change it?

Why is that the adorner layer is always rendered as the top most layer in an application (under AdornerDecorator - refer screenshot)?
Is there a way to change the layer/level on to which the adorners can be drawn?
In the following screenshot, AdornerLayer is added to AdornerDecorator and the Adorners (MyAdorners) are added to this AdornerLayer. But the AdornerLayer is retrieved like this,
AdornerLayer layer1 = AdornerLayer.GetAdornerLayer(button1);
layer1.Add(new MyAdorner(button1));
To answer my second question,
Is there a way to change the layer/level on to which the adorners can be drawn?
I guess I have found a solution. Just place an AdornerDecorator element around the level on to which the adorners needs to be rendered. Any control requiring an adorner layer would use this AdornerDecorator element to place its decorators.
Here I have moved the adorners to a different level using the following code snippet.
<Window x:Class="CustomAdornerLayer.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" Loaded="Window_Loaded">
<Grid>
<StackPanel Background="Yellow" Width="Auto">
<Button>Button3</Button>
</StackPanel>
<AdornerDecorator>
<Grid>
<AdornerDecorator>
<Button x:Name="button1" Margin="70,73,265,158">Button1</Button>
</AdornerDecorator>
<AdornerDecorator>
<Button x:Name="button2" Margin="87,51,248,180">Button2</Button>
</AdornerDecorator>
</Grid>
</AdornerDecorator>
</Grid>
While the AdornerLayer is still queried in the same way,
AdornerLayer layer1 = AdornerLayer.GetAdornerLayer(button1);
layer1.Add(new MyAdorner(button1));
AdornerLayer layer2 = AdornerLayer.GetAdornerLayer(button2);
layer2.Add(new MyAdorner(button2));
Kindly correct me if I am wrong.
Adorner layer is provided by AdornerDecorator. When you ask for the layer for the given control wpf looks for the AdornerDecorator upper visual tree.
Why do you need to change this logic? Adorners system made intentionally this way for decorations to appear above the decorated element.
You can search for AdornerDecorator yourself with VisualTreeHelper

Easier way to scale controls?

Recently I coded an extremely graphical interface in for hi-res displays(1900x1200). Of course my the requirements changed, and it needed to be redone in 1366x768. Rather than retool the app for a fixed resolution(lesson learned), i moved everything into its own ViewBox and recrafted my grid controls to handle this. The app looks great and scales to (nearly)any size without artifacts.
My question is, is there an easier way to accomplish full dynamic control scaling in WPF with putting each control in its own viewbox? ViewBox was the only control I could find to do this, but it can only contain one child element, which made this a VERY tedious process. Is there a better control that can contain child controls that scales?
Why not put a Grid or StackPanel inside the viewBox, and then fill them with the controls?
Something like this
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WfpApplication1="clr-namespace:WfpApplication1"
Title="MainWindow" Height="350" Width="525">
<Viewbox>
<StackPanel>
<CheckBox Content="Hello World!"/>
<TextBlock Text="Hello world"/>
<Button Content="Hello world!"/>
</StackPanel>
</Viewbox>

How to load a grid from XAML codes and add it to a stackpanel dynamically/at runtime?

I generate the XAML codes which actually describe a valid grid control - called the GridXAML. I want to create a grid object and add it to a stackpanel on my form.
How can I 1) create an object from its XAML string value, and 2) add it dynamically to a panel? Please help!
Giving a specific sample context as below.
The generated grid's xaml:
<Grid>
<Textblock Text="abb" />
</Grid>
The current main form of my WPF application.
<Window x:Class="MyApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="333" Width="111">
<StackPanel x:Name="MyStackPanel" Orientation="Vertical">
<!--I want the grid appear here at runtime-->
</StackPanel>
</Window>
All helps are very much appreciated!
Use the XamlReader's XamlReader.Load() or XamlReader.Parse()

Resources