Make WPF Interface Free of display size - c#

Ok, so I'm developing a C# WPF Application. The MainWindow for this app is always fullscreen, but I need to adjust the controls based on resolution. Anyway, I have tried quite a few things to achieve this. Right now, I have set the Grid length & width to Auto. The problem is that my controls shift up and to the left for some reason. Below is my MainWindowXAML. (BTW: The window contains: Image buttons, Labels, Rectangles, and TextBoxes):
<Window x:Name="Menu" x:Class="App.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="App1" FontWeight="Bold" Icon="Images/Core-IconSize.ico" WindowStartupLocation="CenterScreen" WindowStyle="ThreeDBorderWindow" WindowState="Maximized" ResizeMode="CanMinimize" Height="870" Width="1388">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
//Controls here.
</Grid>
</Window>
Edit: Added XAML for controls.

It sounds like you want your controls to scale up or down if the screen size is different; rather than just shift positions.
If this is what you want, you can achieve this effect by putting your Grid inside a Viewbox control. The Viewbox will then automatically scale it's contents up or down to fit the existing real estate.
Also, you may want to remove the height and width properties from your window as they are redundant for a full-screen application. If you want a specific size while you are editing the window in XAML, you can set the designheight and designwidth properties.
Example without the Viewbox:
<Window x:Class="MVVM_Exploration.Windows.wndDataGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="wndDataGrid" Height="300" Width="500">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Button Content="Load Text File" HorizontalAlignment="Left"
Margin="10" Click="LoadTextFile"/>
<Button Content="Save Text File" HorizontalAlignment="Left"
Margin="10" Click="SaveTextFile"/>
</StackPanel>
<TextBlock Grid.Row="1" Text="Some content here"/>
<Button Content="Another Button" Grid.Row="2"
HorizontalAlignment="Left"/>
</Grid>
</Window>
Example with the Viewbox:
<Window x:Class="MVVM_Exploration.Windows.wndDataGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="wndDataGrid" Height="300" Width="500">
<Viewbox>
<Grid Width="200" Height="100">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Button Content="Load Text File" HorizontalAlignment="Left"
Margin="10" Click="LoadTextFile"/>
<Button Content="Save Text File" HorizontalAlignment="Left"
Margin="10" Click="SaveTextFile"/>
</StackPanel>
<TextBlock Grid.Row="1" Text="Some content here"/>
<Button Content="Another Button" Grid.Row="2"
HorizontalAlignment="Left"/>
</Grid>
</Viewbox>
</Window>
Depending on how your grid and it's contents are set up, you may not need to give the actual grid a defined size.

Related

WPF - Manage UI

I want to make something like this type of UI:
There will be two or three buttons always on top with a textbox (no change after window resize).
How can I do this in WPF, actually am new to WPF and I want to do this strictly in .Net & WPF 3.5.
I remember when I started to learn WPF. It was a steep learning curve. You need to look into XAML files to get the UI. For your requirement, the code would look like this...assume you have some background in VS, start new WPF project ect. What you want is some grid and then you can either drag and drop from Toolbox, or you can just type code for your UI elements.
<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="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="90*"/>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="90*"/>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="200*"/>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="90*"/>
<ColumnDefinition Width="5*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="3*"/>
<RowDefinition Height="50*"/>
<RowDefinition Height="3*"/>
<RowDefinition Height="100*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<Button Content="Button" Grid.Column="1" Grid.Row="1" Margin="0,0,0,0"/>
<Button Content="Button" Grid.Column="3" Grid.Row="1" Margin="0,0,0,0"/>
<TextBox Text="Textbox" Grid.Column="5" Grid.Row="1" Margin="0,0,0,0"/>
<Button Content="Button" Grid.Column="7" Grid.Row="1" Margin="0,0,0,0"/>
<Border BorderBrush="Black" BorderThickness="1" Grid.ColumnSpan="7" Grid.Column="1" Height="100" Grid.Row="1" VerticalAlignment="Top">
</Border>
</Grid>

components does not scale properly

For my WPF project in C#, I have to create a menu state which should look like image below
So far, I have created
XAML Code for this window:
<UserControl x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="800">
<Grid Background="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="125"/>
<RowDefinition Height="100"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200*"/>
<ColumnDefinition Width="400*"/>
<ColumnDefinition Width="200*"/>
</Grid.ColumnDefinitions>
<!-- title -->
<Label Grid.Row="0" Grid.Column="1" HorizontalAlignment="Center" FontFamily="Franklin Gothic Heavy">
<Viewbox>
<TextBlock>Title</TextBlock>
</Viewbox>
</Label>
<!-- menu -->
<Grid Grid.Row="2" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="15"/>
<RowDefinition Height="50"/>
<RowDefinition Height="15"/>
<RowDefinition Height="50"/>
<RowDefinition Height="15"/>
<RowDefinition Height="50"/>
<RowDefinition Height="15"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300*"/>
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0" FontFamily="Franklin Gothic Medium">
<Viewbox><TextBlock>State</TextBlock></Viewbox>
</Button>
<Button Grid.Row="2" Grid.Column="0" FontFamily="Franklin Gothic Medium">
<Viewbox><TextBlock>State</TextBlock></Viewbox>
</Button>
<Button Grid.Row="4" Grid.Column="0" FontFamily="Franklin Gothic Medium">
<Viewbox><TextBlock>State</TextBlock></Viewbox>
</Button>
<Button Grid.Row="6" Grid.Column="0" FontFamily="Franklin Gothic Medium">
<Viewbox><TextBlock>State</TextBlock></Viewbox>
</Button>
<Button Grid.Row="8" Grid.Column="0" FontFamily="Franklin Gothic Medium">
<Viewbox><TextBlock>State</TextBlock></Viewbox>
</Button>
</Grid>
</Grid>
</UserControl>
Problem with this window is this components (label and buttons with their contents) does not scale properly. What I want is, when I resize the window I want this components to be proportional to window. Not sure if the grid layout is problem, but how can I fix this components scale properly.
EDIT:
Ok, so I followed your instructions and I like the results (everything seems to scale good enough),
but I have two more minor problems:
1) With a new changes to XAML code, my last button is colliding with the south border of the window, which is not what I want. What I want is an empty space with size of almost exactly (if possible) or close space, like between Label "Title" and north border of the window.
I found solution by defining a new line at the end <RowDefinition Height="*"/>. Not sure if this is a correct way to go.
2) Thus, so far I understand that , 1, 2*,... multiplies the current size. However, it seems I still feel like I don't fully understand it. Currently, I am asking myself, how can I now change the size (width or height in some case) of the button components inside grid layout?
Finally, do I change properties for the size directly to button or via grid layout?
Here is the code for a new window.
<UserControl x:Class="TypeRacer_Client.state.MenuState"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="800">
<Grid Background="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- title -->
<Label Grid.Row="0" Grid.Column="1" HorizontalAlignment="Center" FontFamily="Franklin Gothic Heavy">
<Viewbox>
<TextBlock>Title</TextBlock>
</Viewbox>
</Label>
<!-- menu -->
<Grid Grid.Row="2" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="15"/>
<RowDefinition Height="*"/>
<RowDefinition Height="15"/>
<RowDefinition Height="*"/>
<RowDefinition Height="15"/>
<RowDefinition Height="*"/>
<RowDefinition Height="15"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0" FontFamily="Franklin Gothic Medium">
<Viewbox><TextBlock>State</TextBlock></Viewbox>
</Button>
<Button Grid.Row="2" Grid.Column="0" FontFamily="Franklin Gothic Medium">
<Viewbox><TextBlock>State</TextBlock></Viewbox>
</Button>
<Button Grid.Row="4" Grid.Column="0" FontFamily="Franklin Gothic Medium">
<Viewbox><TextBlock>State</TextBlock></Viewbox>
</Button>
<Button Grid.Row="6" Grid.Column="0" FontFamily="Franklin Gothic Medium">
<Viewbox><TextBlock>State</TextBlock></Viewbox>
</Button>
<Button Grid.Row="8" Grid.Column="0" FontFamily="Franklin Gothic Medium">
<Viewbox><TextBlock>State</TextBlock></Viewbox>
</Button>
</Grid>
</Grid>
</UserControl>
Use star sizing (ratios) to size your grid's rows etc. Like , 2, 4* etc. This will make the rows and columns keep the same ratios, no matter what size the window is, like this:
<RowDefinition Height="*" />
<RowDefinition Height="2* /> //this will be 2x the previous row's height
Style the buttons for consistent width/height/other properties etc.
<Style TargetType="Button" x:Name="SomeButtonStyle">
<Setter Property="Width" Value="90" />
</Style>
then , for each button you want the same height/width/whatever property:
<Button Style="{StaticResource SomeButtonStyle}" />
This will keep you from putting a width, height or font etc. in EVERY button you made, and makes it much faster to change the value in one place, instead of every button.

wpf grid and stackpanel fill

I have a grid with 2 rows one for a name and button and the other for output.
I want the first row to stretch the full width and the button to align to the right.
Wondering what I am missing as I thought the stackpanel would fill the width.
<Window x:Class="Sample.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">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0" >
<TextBox Name="NameTextBox" MinWidth="150" HorizontalAlignment="Stretch"/>
<Button Margin="10,0" Name="AlertButton" Content="Say Hello" HorizontalAlignment="Stretch" />
</StackPanel>
<TextBox Name="OutpuTextBox" MinLines="5" Grid.Row="1" Grid.Column="0"/>
</Grid>
</Window>
Horizontal StackPanel ignores horizontally alignment of its children. You can change your layout to 2 columns and put Button in the second column of first row and set bottom TextBox to span across 2 columns
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox Name="NameTextBox" MinWidth="150" HorizontalAlignment="Stretch"/>
<Button Margin="10,0" Name="AlertButton" Content="Say Hello" HorizontalAlignment="Stretch" Grid.Column="1" />
<TextBox Name="OutpuTextBox" MinLines="5" Grid.Row="1" Grid.ColumnSpan="2"/>
</Grid>

Weird Gridsplitter resizing behaviour

Got his XAML :
<Window x:Class="correctionTests.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">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Menu Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" IsMainMenu="True">
<MenuItem Header="_Ouvrir" Click="Open_Click"/>
</Menu>
<GroupBox Header="Tests : " VerticalAlignment="Top" Grid.Column="0" Grid.Row="1">
<ListBox HorizontalAlignment="Left" VerticalAlignment="Top" x:Name="testList"/>
</GroupBox>
<GridSplitter HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Grid.Column="1"
Grid.Row="1"
Width="5"
Background="#FFBCBCBC"/>
<UserControl x:Name="userContent" Grid.Column="2" Grid.Row="1"/>
</Grid>
</Window>
Now the problem is that the size of the controls on the column 0 is diminishing when i pull the gridsplitter to the RIGHT, on the other hand the size of the controls of the column 0 is increasing while pulling the gridsplitter to the left.
I already found this link on stack that suggested to change the first column's width to Auto.
The problem is : if i do that, the controls does not resize anymore.
How can i do so that my controls get all the width available ? (with the expected gridsplitter behaviour) ?
As your GridSplitter is on separate column, you have to
set ResizeBehavior="PreviousAndNext"

WPF Listbox grows outside screen size (MVVM light)

I have a typical MVVM structure. A mainwindow consists of some labels and a viewmodel (bound as ContentControl). This viewmodel has a listbox where I add entries. As the list grows the height of my viewmodel grows as well and thus the height of the whole application. Unfortunately the size doesn't stop at the edge of the screen and just grows out of the screen. I tried all the different size-restrictions on the mainwindow, the viewmodel is stretched in both dimensions.
Furthermore, I tried to get a scrollbar for the listbox but didn't succeed (or it's just there but not enabled if I force it.)
How can I restrict the maximal size to be the resolution of the screen (fullscreen) and get a scrollbar for the listbox when the size is reached?
€: Okay, here should be the relevant part of my code. I tried a fixed size of 1024x768 but even that doesn't work.
MainWindow.xaml
<Window x:Class="SWS.MainWindow"
DataContext="{Binding Main, Source={StaticResource Locator}}"
Width="1024"
Height="768"
MaxWidth="1024"
MaxHeight="768">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ContentControl Grid.Row="0" Content="{Binding CurrentViewModel}" />
</Grid>
</Window>
The ViewModel in question
<UserControl x:Class="SWS.Views.ProgramView"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<DockPanel Grid.Row="0">
<Label Width="65" Content="{x:Static p:Resources.PrV_Number}" />
<Label Width="75" Content="{x:Static p:Resources.PrV_Weight}" />
<Label Width="55" Content="{x:Static p:Resources.PrV_Action}" />
<Label Content=" " />
</DockPanel>
<ListBox Grid.Row="1"
VerticalAlignment="Stretch"
ItemsSource="{Binding ParticleCollection}"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel>
<TextBlock Text="{Binding ID}" Width="53" />
<TextBlock Text="{Binding Weight, StringFormat=F4}" Width="65" />
<TextBlock Text="{Binding Action}" Width="52" />
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>
You need to set the row height to * on your Window for ContentControl and your ListBox in UserControl to fill available space than try to get what it needs.
This worked fine:
MainWindow.xaml:
<Window x:Class="SWS.MainWindow"
DataContext="{Binding Main, Source={StaticResource Locator}}"
Width="1024"
Height="768"
MaxWidth="1024"
MaxHeight="768">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentControl Grid.Row="0" Content="{Binding CurrentViewModel}" />
</Grid>
</Window>
and UserControl:
<UserControl x:Class="SWS.Views.ProgramView"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
...
</Grid>
</UserControl>
Could also do this in a couple more ways:
In your Window you can just remove the <Grid.RowDefinitions>...<Grid.RowDefinitions> completely. The default behavior is what your looking for.
When you have more than 1 row you can either choose to specify Height="*" or just remove the Height Property from the RowDefinition
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>

Categories