Proportionately resize entire Visual Basic WPF application + contents - wpf

I have a third party WPF application I am creating for Windows that I need to be resizable.
I have gotten it to resize (proportionally) with the grip but cannot get everything else to work correctly in regards to anchor/layout ect. The buttons would not align correctly with the background no matter what I did.
I'm wondering if there is an easier way to simply resize the whole application and all the contents via the grip. It would look like you would be resizing the photo below.
I have a window, grid (with background) buttons and text. Below is a screenshot of the iOS version of the app. The program will continue to be a 4:3 ratio.

Seems most of this is straightforward WPF, apart from the requirement to keep the buttons square as the window is resized horizontally or vertically. Ideally we would force a horiz resize to force the height, and vice versa, but a bit of googling seems to indicate this is surprisingly difficult to achieve with pro-looking results. So far this xaml is the best I've come up with. Try it with and without the viewbox:
<Window x:Class="WpfApp1.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"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="260" Width="260">
<Viewbox Stretch="Uniform">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Button Content="Button" Margin="4"/>
<Button Content="Button" Grid.Column="1" Margin="4"/>
<Button Content="Button" Grid.Column="2" Margin="4"/>
<Button Content="Button" Grid.Row="1" Margin="4"/>
<Button Content="Button" Grid.Column="1" Grid.Row="1" Margin="4"/>
<Button Content="Button" Grid.Column="2" Grid.Row="1" Margin="4"/>
<Button Content="Button" Grid.Row="2" Margin="4"/>
<Button Content="Button" Grid.Column="1" Grid.Row="2" Margin="4"/>
<Button Content="Button" Grid.Column="2" Grid.Row="2" Margin="4"/>
</Grid>
</Viewbox>

Related

WPF Forms Integration - A Problem with Grid

I am doing a feasibility study to find out whether and how we can integrate a Forms application into a WPF project.
I started with a simple example and immediately encountered a problem (here is the code):
<Window x:Class="TestFormsIntegration.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"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
xmlns:local="clr-namespace:TestFormsIntegration"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="*"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="Menue Bar" HorizontalContentAlignment="Center" Background="BlanchedAlmond" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
<ScrollViewer x:Name="scrollViewer" Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="200" />
<RowDefinition Height="200" />
<RowDefinition Height="200" />
<RowDefinition Height="200" />
</Grid.RowDefinitions>
<WindowsFormsHost Grid.Row="0" HorizontalAlignment="Center" Height="190" VerticalAlignment="Center" Width="250">
<wf:Button Text="Button 0" Height="180" Width="200" BackColor="Gray" />
</WindowsFormsHost>
<WindowsFormsHost Grid.Row="1" HorizontalAlignment="Center" Height="190" VerticalAlignment="Center" Width="250">
<wf:Button Text="Button 1" Height="180" Width="200" BackColor="Gray"/>
</WindowsFormsHost>
<WindowsFormsHost Grid.Row="2" HorizontalAlignment="Center" Height="190" VerticalAlignment="Center" Width="250">
<wf:Button Text="Button 2" Height="180" Width="200" BackColor="Gray" />
</WindowsFormsHost>
<WindowsFormsHost Grid.Row="3" HorizontalAlignment="Center" Height="190" VerticalAlignment="Center" Width="250">
<wf:Button Text="Button 3" Height="180" Width="200" BackColor="Gray" />
</WindowsFormsHost>
</Grid>
</ScrollViewer>
<Label Grid.Row="2" Content="Status Bar" HorizontalContentAlignment="Center" Background="Wheat" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</Grid>
</Window>
In a grid with 4 rows I place 4 forms buttons. When I run the code, the inner grid crosses the boundaries and overwrites the labels at the top and bottom (indicating Menu and Status Bar) and takes up the height of the entire window.
Does anyone know this behaviour and how to fix it?
Hint: Try a larger value for height (you have Height="450"), because the sum of the height of your elements is just higher (200 * 4) and don't forget the labels.
I have found the solution here:
WindowsFormsHost ZOrder
Here I read:
In a WPF user interface, you can change the z-order of elements to control overlapping behavior. A hosted Windows Forms control is drawn in a separate HWND, so it is always drawn on top of WPF elements.
But this article also contains an answer with a solution!
You can do a little trick. When you declare an WindowsFormsHost, it's parent is first HWND component. Usually it's root window. So, clip area for controls is whole window.
But there's a way to create "intermediate" HWND item to clip WinForms area over ScrollViewer. Just place another WindowsFormsHost with ElementHost.
Thank you for your answer, ds1709.

Matching grid and window size WPF

I just started using WPF (instead of winforms) and I'm trying to create a fixed-sized window (see image).
Problem is, whenever I run the app the bottom right corner gets messed up, having near zero space between the button and the edge. (see other image)
Here's the XAML code (mostly generated by the Visual Studio designer)
<Window x:Class="UseCaseHelper.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"
xmlns:local="clr-namespace:UseCaseHelper"
mc:Ignorable="d"
Title="UseCaseHelper" Height="500" Width="900">
<Grid>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75"/>
<Button x:Name="button1" Content="Button" HorizontalAlignment="Left" Margin="809,441,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</Window>
I've tried googling for a solution without much success. Hopefully someone can point out what I'm doing wrong here.
I always find DockPanel more flexible in these settings. Instead of the VerticalAlighnment and the Margin you set, you can set DockPanel.Dock to Left, Right, Bottom or Top.
<DockPanel LastChildFill="False">
<Button DockPanel.Dock="Top"
Content="Button" HorizontalAlignment="Left" Margin="10,10,0,0"
Width="75"/>
<Button DockPanel.Dock="Bottom"
Content="Button" HorizontalAlignment="Right" Margin="0,0,10,10" Width="75"/>
</DockPanel>
Note that you can also use Margin="10" for both Buttons.
However, if you want to use Grid, you can use the following structure:
<Grid>
<Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,10,0,0"
Width="75"/>
<Button Content="Button" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,10,10" Width="75"/>
</Grid>
Note that in this case they will overlap if the Window is small enough.
Another option is to add RowDefinitions and ColumnDefinitions to the Grid:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button
Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,10,0,0"
Width="75"/>
<Button Grid.Column="2" Grid.Row="2"
Content="Button" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,10,10" Width="75"/>
</Grid>
Its perfomance is better than the other two, if Window is very small.

Button inside a custom skewed window doesn't allways get mouseEnter event

Here is my code:
<Window x:Class="WPFStackOverFlow.SkewWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
AllowsTransparency="True" WindowStyle="None" Background="Transparent"
Title="MainWindow" Height="600" Width="687">
<Border BorderBrush="Green" BorderThickness="2" Background="White" Width="360" Height="360">
<Border.RenderTransform>
<SkewTransform AngleX="-23" AngleY="10"></SkewTransform>
</Border.RenderTransform>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="23" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Grid.Row="0" Content="X" Width="23" Name="button1" HorizontalAlignment="Right" Click="button1_Click" Height="23" VerticalAlignment="Bottom"/>
<Grid Grid.Row="1">
<Button Height="100" Width="200"></Button>
<TextBlock Text="Some very very long Text" HorizontalAlignment="Center"/>
</Grid>
</Grid>
</Border>
When I move the mouse cursor over the button sometimes it get focus and sometimes it doesn't. How can I make the button inside this custom window to be like a button in a regular window?
I don't think you can apply transformations to windows.
You can apply them to the controls inside windows.
If you need to simulate transformations to windows you can try something similar to what is described in the answer to this question.

How to layout controls in the top right hand corner in XAML/Silverlight?

I am going through the process of designing my first Silverlight application based upon the PivotViewer control from Silverlight 4. I am having problems organizing the bar at the top as per my design:
(source: richard-slater.co.uk)
I have found ways of left aligning the Logo and Title, a way of right aligning the buttons with various combinations of panels however there are two major problems with it.
The XAML looks really really ugly, nesting panels seems to work but doesn't seem like good practice.
I can't seem to find a way of handling resizing the window down without either clipping or overlapping.
I have acheived the best results with the following code:
<StackPanel x:Name="LayoutHeader" Margin="4" Height="50" Grid.Column="0" Grid.Row="0" Orientation="Horizontal">
<Image x:Name="LogoImage" Height="50" Width="50" Source="/EVEMonPivot;component/EVEMonLogoBlue.png" Grid.Column="0" Grid.Row="0" />
<TextBlock x:Name="TitleText" Height="50" Text="EVEMon Pivot" FontSize="40" Grid.Column="1" Grid.Row="0" VerticalAlignment="Center" FontWeight="Bold" Padding="10,0,0,0" />
</StackPanel>
<StackPanel x:Name="NavHeader" Margin="4" Height="50" Grid.Column="0" Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Right">
<Button x:Name="StackExButton" Style="{StaticResource NavButton}" Click="StackExButton_Click">EVE Online StackExchange</Button>
<Button x:Name="BugsButton" Style="{StaticResource NavButton}">Bugs & Suggestions</Button>
</StackPanel>
I intend to move some of the properties into styles, however it still feels messy.
The above code can also result in the following in small windows:
(source: richard-slater.co.uk)
Is there a better way?
If you don't like nesting panels, a Grid might be a better option. With your four elements, have a five column grid like this:
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Image x:Name="LogoImage"
Height="50"
Width="50"
Source="/EVEMonPivot;component/EVEMonLogoBlue.png"
Grid.Column="0" />
<TextBlock x:Name="TitleText"
Height="50"
Text="EVEMon Pivot"
FontSize="40"
Grid.Column="1"
Grid.Row="0"
VerticalAlignment="Center"
FontWeight="Bold"
Padding="10,0,0,0" />
<Button x:Name="StackExButton"
Grid.Column="4"
Style="{StaticResource NavButton}"
Click="StackExButton_Click">EVE Online StackExchange</Button>
<Button x:Name="BugsButton"
Grid.Column="5"
Style="{StaticResource NavButton}">Bugs & Suggestions</Button>
</Grid>
This sets four columns to Auto-size, so they adjust to the size of your UI elements, and the centre column is Star-sized so it fills the rest of the space between them.
While you can use a star-sized grid column to enforce a collapsible region between the controls, you're still left to account for what happens when there simply isn't enough room (eg. 600 pixels of display in a 400-pixel wide area.) What I think you need is a ScrollViewer, which is a ContentControl that lets you determine when scroll bars appear.
In the markup below I am doing 2 things: First, I am using the Silverlight toolkit's DockPanel to isolate the left and right sections of the display (a very similar thing can be accomplished with a 3-column Grid with Cols 0 and 2 set to "Auto" and Col 1 set to "*", but the specific use of Left and Right in the DockPanel may make the intent more readable.) Second, the whole thing is being wrapped in a ScrollViewer with the HorizontalScrollBarVisibility set to "Auto" - when the contents is too big to fit, put up a scrollbar.
<UserControl xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit" x:Class="SilverlightApplication2.MainPage"
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"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="0" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<toolkit:DockPanel >
<StackPanel toolkit:DockPanel.Dock="Left" Orientation="Horizontal" VerticalAlignment="Top" Height="50" Margin="5">
<TextBlock Text="Some long text" FontSize="30"/>
</StackPanel>
<StackPanel toolkit:DockPanel.Dock="Right" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Right" Height="50" Margin="5">
<Button Content="First Button" Margin="5"/>
<Button Content="Second Button" Margin="5"/>
</StackPanel>
</toolkit:DockPanel>
</ScrollViewer>
<TextBlock Grid.Row="1" Text="Body Content (DataGrid, etc.)" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>

XAML Controls offsetting themselves, becoming invisible in Blend and browser

I'm having a problem, visible at runtime and in Expression Blend, where the text blocks (not text boxes, buttons, or custom controls) in my layout grid keep pushing themselves outside their cells, rendering them invisible. If I touch any of their properties in Blend (such as incrementing and then decrementing one of the margins), they become visible in Blend, but still not at runtime. Below is a screenshot showing the phenomenon in Blend. You see the design guides pointed to where the control should be, but its actual location above the top of the canvas.
Controls are offset in Blend http://tinyurl.com/y9ttscf
Update:
Below I've posted the XAML, with the VisualStateGroups removed (since they add considerable complexity to the XAML and the problem manifests itself without them). The control selected above is "loginTextBlock" below.
<navigation:Page
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"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
mc:Ignorable="d" xmlns:UserControls="clr-namespace:MyClient.UserControls" xmlns:MyClient_Controls="clr-namespace:MyClient.Controls;assembly=MyClient.Controls" xmlns:controlsToolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit" x:Class="MyClient.Views.Login"
d:DesignWidth="640" d:DesignHeight="480"
Title="Login"
>
<Grid x:Name="LayoutRoot">
<Grid HorizontalAlignment="Center" Margin="0,16,0,0" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="loginTextBlock" HorizontalAlignment="Center" Style="{StaticResource HeaderTextStyle}" VerticalAlignment="Center" Text="Login" Grid.ColumnSpan="2" Margin="0,8"/>
<TextBlock x:Name="usernameTextBlock" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.Row="1" Text="User name:" TextWrapping="Wrap"/>
<TextBox x:Name="usernameTextBox" HorizontalAlignment="Left" Margin="8,8,0,8" VerticalAlignment="Center" Width="175" Grid.Column="1" Grid.Row="1" TextWrapping="Wrap" TabIndex="0" FontSize="16" Height="28" Padding="2"/>
<TextBlock x:Name="passwordTextBlock" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.Row="2" Text="Password:" TextWrapping="Wrap"/>
<PasswordBox x:Name="passwordBox" HorizontalAlignment="Left" Margin="8,8,0,8" VerticalAlignment="Center" Width="175" Grid.Column="1" Grid.Row="2" TabIndex="1" FontSize="16" Height="28" Padding="2"/>
<Button x:Name="okButton" Height="32" HorizontalAlignment="Center" Margin="0,16,0,0" VerticalAlignment="Top" Width="96" Content="OK" Grid.Row="3" TabIndex="2" Click="okButton_Click" Grid.ColumnSpan="2"/>
<UserControls:StatusTextBlockControl x:Name="verifyingStatusTextBlockControl" Margin="8,16,8,8" VerticalAlignment="Center" Grid.Row="4" HorizontalAlignment="Center" Grid.ColumnSpan="2" Text="Verifying credentials..."/>
<MyClient_Controls:LoginAttemptsCounter x:Name="loginAttemptsCounter" HorizontalAlignment="Center" Margin="8" VerticalAlignment="Center" Grid.ColumnSpan="2" Grid.Row="5" FirstFailureMessage="Please re-enter your Windows credentials.
After 2 more failed attempts, your account will be locked." Height="30"/>
</Grid>
</Grid>
</navigation:Page>
For some reason, when my "LoginAttemptsCounter" control is in the grid (at the bottom), it was messing up the TextBlock controls. Instead, I changed my layout to wrap the grid within a StackPanel and place the LoginAttemptsCounter in the StackPanel below the grid rather than in the grid's bottom row. That has worked.
The key thing is that my custom control can't be within the same container (either the StackPanel or the Grid) as the TextBlocks.

Resources