When resizing window elements move - c#

I am working on a wpf bingo app for learning.
When the app is in full screen it looks how i want it:
However, when the window is minimized the elements move out of the positions I want them:
what can I do to stop this and keep the elements in one place no matter what window size.
Below is my complete XAML code:
<Window x:Class="Bingo_Game.MainGame"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Bingo_Game"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainGame" WindowStartupLocation="CenterScreen" WindowState="Maximized" Height="704.2">
<Window.Background>
<ImageBrush ImageSource="Images/background.jpg"/>
</Window.Background>
<Grid>
<DataGrid Name="grid" ItemsSource="{Binding}" Height="300"
AutoGenerateColumns="False" HeadersVisibility="None" Background="Transparent" BorderThickness="0" CanUserAddRows="false"
VerticalScrollBarVisibility="Disabled" HorizontalAlignment="Center" VerticalAlignment="Top" RowHeight="40" Margin="10,0" HorizontalContentAlignment="Center">
<DataGrid.Resources>
<local:ItemExistInRangeConverter x:Key="ItemExistInRangeConverter"/>
<Style x:Key="BackgroundColourStyle" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource ItemExistInRangeConverter}">
<Binding Path="Text" RelativeSource="{RelativeSource Self}"/>
<Binding Path="DataContext.RangeNumbers"
RelativeSource="{RelativeSource FindAncestor,
AncestorType=DataGrid}"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Background" Value="LightGreen" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=Number}"
ElementStyle="{StaticResource BackgroundColourStyle}" MinWidth="65">
</DataGridTextColumn>
</DataGrid.Columns>
<DataGrid.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</DataGrid.ItemsPanel>
</DataGrid>
<Button Content="Roll Number" Margin="333,139,323,484" Width="104" Click="newNumber" Height="50" RenderTransformOrigin="-1.01,-1.46" HorizontalAlignment="Center" VerticalAlignment="Center" >
<Button.Effect>
<DropShadowEffect/>
</Button.Effect>
</Button>
<TextBlock HorizontalAlignment="Center" Margin="240,187,217,340" TextWrapping="Wrap" Name="number" VerticalAlignment="Center" Height="146" Width="303" FontSize="120" FontWeight="Bold" TextAlignment="Center" Foreground="Black" Grid.IsSharedSizeScope="True"/>
<DataGrid HorizontalAlignment="Left" Margin="0,544,0,0" VerticalAlignment="Top" RenderTransformOrigin="-2.917,-2.923" Height="119" Width="330" Name="calledGrid" ItemsSource="{Binding}" />
<TextBlock HorizontalAlignment="Center" Height="33" Margin="240,333,226,307" TextWrapping="Wrap" VerticalAlignment="Center" Width="294" Name="noneLeft" FontSize="16" FontWeight="Bold" TextAlignment="Center" />
<TextBlock HorizontalAlignment="Center" Height="33" Margin="240,300,226,340" TextWrapping="Wrap" VerticalAlignment="Center" Width="294" Name="callTB" TextAlignment="Center" FontSize="20" />
</Grid>
</Window>

In addition to the MSDN link DROP table users listed, have a read of this overview of the WPF Panel elements to get a feel for how to approach UI layout in WPF. ALhtough you can drag and drop (and resize) your controls within Visual Studio, it often leads to layouts that don't scale well, and introduces additional compilacations (the extra Margin properties on many of your controls).
If you aren't going to stop your users from resizing your control, it's worth thinking about how you'd like the elements behave when the window is manipulated, should elements scale, move around, stay fixed to a particular window edge, etc.
There are many different ways to layout your UI with the various panels, but your desired behaviour dictates which is the easiest/most appropriate.
Here's a small (but not very neat) mock up using a Grid, to roughly approximate your first case (some of your elements replaced by a few simple labels).
<Grid Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Content="Your DataGrid" Grid.Column="1" Grid.Row="0" Background="Red" Grid.ColumnSpan="3"/>
<Label Content="Your Other DataGrid" Grid.Column="0" Grid.Row="1" Background="Green" Grid.ColumnSpan="2"/>
<Label Content="Your Button" Grid.Column="2" Grid.Row="2" Background="Gray" Height="40" Width="100"/>
<Label Content="41" Grid.Column="2" Grid.Row="1" Background="White" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="30"/>
</Grid>
It will produce something that looks like this:
Play around resizing it, some elements will stretch, some (with fixed height/width), will remain the same size, and move around relative to the window size.
If you wish to dock elements to the side of your window, have a look at the DockPanel, if you need to collect a few controls together, check out the StackPanel.

Check this out. It points out that to prevent this you can set up a grid and put the elements in defined size columns and rows to keep them from re-sizing with the window.
Also, a good article that you may look at here about Windows Presentation Foundation (WPF) layout system.

Related

C# WPF - Dockpanel's children collapsed not resizing the other visible childs

I'm sorry if I didn't find any relative post/questions regarding my small annoying issue.
I have a WPF window with a DockPanel (LastChildFill = True) that hosts three controls :
One Button (OK)
One label (Title)
One Border with a listbox in it
What I do is when the test in process is "pass" it has no data to push in the listbox so I make it collapsed and then I would like the Title label to be centered in the available space that is not used by the listbox and its border.
When I have a "fail" or an "error", I have data to put in the listbox and then it is visible and everything is just as expected.
I tried many things before coming here and I lost enough time on this as I need to get other stuff done by the time I'm writing here.
Can anyone point me out how to solve my issue (centering label when listbox+border is collapsed) ?
Here is my xaml code for this window :
<Window x:Class="NI.TestStand.WPFControls.Views.DisplayBannerView"
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:NI.TestStand.WPFControls"
mc:Ignorable="d"
Title="DisplayBanner" x:Name="DisplayBannerMessage" Height="500" Width="800" MinHeight="300" MinWidth="500">
<Window.Resources>
<Style x:Name="BaseWindowFont" TargetType="Window">
<Setter Property="FontFamily" Value="Arial"></Setter>
<Setter Property="FontSize" Value="16"></Setter>
</Style>
</Window.Resources>
<Grid>
<Border BorderBrush="Black" BorderThickness="2">
<DockPanel LastChildFill="True">
<Button
x:Name="butOK"
DockPanel.Dock="Bottom"
Margin="10" Content="OK"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Padding="10" Width="150"
Click="butOK_Click"/>
<Label
x:Name="main_message"
Padding="15"
FontSize="50"
Content="MAIN_MSG"
DockPanel.Dock="Top"
HorizontalAlignment="Center"
VerticalContentAlignment="Center" />
<Border BorderBrush="Chocolate" BorderThickness="2" Margin="10" Name="messages_border">
<ListBox
Background="{Binding ElementName=DisplayBannerMessage, Path=Background}"
Foreground="Black"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.CanContentScroll="True"
VerticalContentAlignment="Top"
VerticalAlignment="Stretch"
x:Name="detail_message">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" ToolTip="{Binding}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
</DockPanel>
</Border>
</Grid>
</Window>
Here are the images that shows a PASS and an ERROR to show the difference.
The PASSED title message in the green lime window should go in the middle of the window as the listbox is collapsed..
Thanks for all your help and time
I would design the whole thing like this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border BorderBrush="Black" BorderThickness="2"
Grid.RowSpan="{Binding PassErrorBooleanProperty, Converter={StaticResource BoolToRowSpanConverter}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label
x:Name="main_message"
Padding="15"
FontSize="50"
Content="MAIN_MSG"
DockPanel.Dock="Top"
HorizontalAlignment="Center"
VerticalContentAlignment="Center" />
<Border Grid.Row="1" BorderBrush="Chocolate" BorderThickness="2" Margin="10" Name="messages_border"
Visibility="{Binding PassErrorBooleanProperty, Converter={StaticResource BoolToVisibilityConverter}}">
<ListBox
Background="{Binding ElementName=DisplayBannerMessage, Path=Background}"
Foreground="Black"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.CanContentScroll="True"
VerticalContentAlignment="Top"
VerticalAlignment="Stretch"
x:Name="detail_message">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" ToolTip="{Binding}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
<Button Grid.Row="2"
x:Name="butOK"
DockPanel.Dock="Bottom"
Margin="10" Content="OK"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Padding="10" Width="150"
Click="butOK_Click" />
</Grid>
</Border>
</Grid>
There are two bindings to PassErrorBooleanProperty (which I've made up as something you'd use to indicate the result, you might have something else in place for this already), and you'd need two different converters, one for converting to a Visibility, and one for converting to an int (Grid.RowSpan).
When the value is true (Pass), you'd return Visibility.Collapsed and 2 from the converters. When the value is false, you'd return Visibility.Visible and 1.
Let me know if you need more info on the converters, though there is lots of information out there on using IValueConverter to create Boolean to Visibility converters, etc.

WPF XAML Custom Listbox Does Not Position Elements Correctly

I am trying to implement a custom multi-page dialog that takes an arbitrary number of visuals (slides) and displays them. The desired behavior would be that the selected item would appear at the top-center of the display area in the foreground. The previous slide would be at the bottom-left with a lower z-index, and the next slide would be at the bottom-right with a lower z-index. "Previous" and "Next" buttons would set the selected index. In the set method for the index, I loop through the slides and set an integer value called "SelectionState" based on whether each slide is hidden, selected, just before the selected one, or just after the selected one. I am trying to position the slides based on this integer using IValueConverters.
For my Listbox.ItemsPanelTemplate, I tried using a Grid. In the ItemsTemplate, I was setting the Grid.Column and Grid.Row using IValueConverters. Stepping through code, I can see that the value converters are being called, and that they are returning appropriate values, but all items appear in row 0, column 0 anyway.
After getting frustrated, I tried changing the Grid to a Canvas and setting the Canvas.Left and Canvas.Top properties, and again, I can see that I am getting good values back from the converter, but all items position themselves in the top-left corner anyway. (This code is shown, but commented out)
Since I know the value converters are behaving as expected, does anybody else see what I am doing wrong? Thank you in advance for any suggestions!
<Grid x:Name="DialogLayer">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="420" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="1100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListBox x:Name="lbSlides" ItemsSource="{Binding CurrentFormSet.InterviewSlides}" Grid.Column="1" Grid.Row="1" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Hidden">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250" />
<ColumnDefinition Width="250" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="250" />
<ColumnDefinition Width="250" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition Height="300" />
<RowDefinition Height="60" />
</Grid.RowDefinitions>
</Grid>
<!--<Canvas Grid.Row="1" Grid.Column="1" />-->
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<!--<Border BorderBrush="Black" BorderThickness="1" Width="600" Height="360" Canvas.Top="{Binding SelectionState, Converter={StaticResource SelectionStateToCanvasTopConverter}}" Canvas.Left="{Binding SelectionState, Converter={StaticResource SelectionStateToCanvasLeftConverter}}" Panel.ZIndex="{Binding SelectionState, Converter={StaticResource SelectionStateToZIndexConverter}}">
<TextBlock Text="Hello World" />
</Border>-->
<Border BorderBrush="Black" BorderThickness="1" Width="600" Height="360" Grid.Column="{Binding SelectionState, Converter={StaticResource SelectionStateToGridColumnConverter}}" Grid.Row="{Binding SelectionState, Converter={StaticResource SelectionStateToGridRowConverter}}" Panel.ZIndex="{Binding SelectionState, Converter={StaticResource SelectionStateToZIndexConverter}}">
<TextBlock Text="Hello World" />
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
You have to set those properties on the item container (i.e. the ListBoxItem) by setting the ItemContainerStyle property:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Grid.Column" Value="{Binding SelectionState, ...}"/>
<Setter Property="Grid.Row" Value="{Binding SelectionState, ...}"/>
<Setter Property="Panel.ZIndex" Value="{Binding SelectionState, ...}"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1" Width="600" Height="360">
<TextBlock Text="Hello World" />
</Border>
</DataTemplate>
</ListBox.ItemTemplate>

Detect virtual keyboard when focusing on a TextBox inside a userControl

I have a the Following FlipView in a winRT project
<FlipView x:Name="Flip" GotFocus="FlipView_GotFocus" Grid.Row="1" ItemsSource="{Binding Controls, ElementName=pageRoot}" SelectedItem="{Binding SelectedControl, ElementName=pageRoot, Mode=TwoWay}">
<FlipView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<ContentPresenter Content="{Binding}" />
</Grid>
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
inside of it i will have several usercontrols that have some TextBox, but when i focus in one of the TextBox , the virtual Keyboard gets in front of the other TextBox, it doesnt "lift" the app like it normally does when i have a simple page with TextBoxs.
Is there a way to detect Keyboard showing up and pulling the view of the app up?
Here is one of the UserControl im using
<UserControl.Resources>
<ResourceDictionary>
<common:ByteArrayToBitmapImageConverter x:Key="ByteArrayToBitmapImageConverter" />
<common:StringToValidityConverter x:Key="StringToValidityConverter" />
</ResourceDictionary>
</UserControl.Resources>
<StackPanel>
<StackPanel Style="{StaticResource SubHeaderStyle}">
<Image Source="/Images/Contract/Sales.png" Style="{StaticResource SubHeaderImageStyle}" />
<TextBlock x:Uid="Sale" Style="{StaticResource SubHeaderTextStyle}" />
</StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Image Grid.RowSpan="6" Width="300" Source="{Binding Picture, Converter={StaticResource ByteArrayToBitmapImageConverter}}" />
<TextBlock x:Uid="SalesOffice" Grid.Row="1" Grid.Column="2" />
<TextBox Grid.Row="1" Grid.Column="3" Text="{Binding Office, Mode=TwoWay}" Style="{StaticResource TextBoxStyle}"
common:TextBoxBehavior.Validity="{Binding Text, RelativeSource={RelativeSource Self}, Converter={StaticResource StringToValidityConverter}}" />
<TextBlock x:Uid="SalesAgent" Grid.Row="2" Grid.Column="2" />
<TextBox Grid.Row="2" Grid.Column="3" Text="{Binding AgentName, Mode=TwoWay}" Style="{StaticResource TextBoxStyle}"
common:TextBoxBehavior.Validity="{Binding Text, RelativeSource={RelativeSource Self}, Converter={StaticResource StringToValidityConverter}}" />
<TextBlock x:Uid="MobilePhone" Grid.Row="3" Grid.Column="2" />
<TextBox Grid.Row="3" Grid.Column="3" Text="{Binding MobilePhone, Mode=TwoWay}" Style="{StaticResource TextBoxStyle}"
common:TextBoxBehavior.Validity="{Binding Text, RelativeSource={RelativeSource Self}, Converter={StaticResource StringToValidityConverter}}" InputScope="Number" />
<TextBlock x:Uid="EmailAddress" Grid.Row="4" Grid.Column="2" />
<TextBox Grid.Row="4" Grid.Column="3" Text="{Binding EmailAddress, Mode=TwoWay}" Style="{StaticResource TextBoxStyle}"
common:TextBoxBehavior.Validity="{Binding Text, RelativeSource={RelativeSource Self}, Converter={StaticResource StringToValidityConverter}}" />
</Grid>
</StackPanel>
and here is how it looks
Edit:
seems that i can detect the keyboard with
Windows.UI.ViewManagement.InputPane.GetForCurrentView().Showing
Windows.UI.ViewManagement.InputPane.GetForCurrentView().Hidding
now i just need to learn how to pull my view up.
As you found, you can use the InputPane's Showing and Hiding events to detect the InputPane's visibility changes. The InputPaneVisibilityEventArgs includes the OccludedRect that it will cover, and you can apply a RenderTransform to your page to Translate it out of the way.
<Page.RenderTransform>
<CompositeTransform x:Name="pageTransform"/>
</Page.RenderTransform>
And a painfully naive implementation:
void Page_Showing(InputPane sender, InputPaneVisibilityEventArgs args)
{
// We probably want something more sophisticated to make sure the
// focus control and any dependencies are in view
pageTransform.TranslateY -= args.OccludedRect.Height;
// Tell the InputPane we already handled things so it doesn't move the page again
args.EnsuredFocusedElementInView = true;
}
void Page_Hiding(InputPane sender, InputPaneVisibilityEventArgs args)
{
pageTransform.TranslateY = 0;
args.EnsuredFocusedElementInView = true;
}
In reality you'll want to do the math to make sure the necessary controls are in view. You can use animations to make the shift more smooth. If you want to get even more creative you can switch to a new visual state which has just the necessary fields for editing in a more friendly layout. In your UserControl case you may want to shift just the control rather than the page.
Also give it a test on a Windows 10 desktop since the soft-keyboard behavior will interact a bit differently with a windowed app.

Remove margin and padding dynamically WPF

I am currently doing a page with a form in it in WPF. There are two textboxes and one listbox with a button to add some elements in the listbox. In one mode (edit mode), I want everything to be visible so that the user will be able to edit the textboxes and add elements in the listbox. In the other mode (view mode), I binded the Visibility property so that when in this mode, everything except the listbox appears (and the listbox takes the whole place) so that the user can just see what existing elements are in the listbox.
Now my problem is, in the edit mode I give a Margin="10" margin, but in view mode I would like the listbox to take the full page width/height (so I would like to remove that margin). How would I go to do this?
My XAML (some user controls are encapsulated in a framework that I am using, but it shouldn't affect my question):
<Grid x:Name="MainScope" pres:OneTheme.Theme="Content">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="53*" />
</Grid.RowDefinitions>
<pres:OneContentLayout Mode="List" Grid.Row="3" Margin="10" >
<pres:OneListBox x:Name="ListBox" BorderBrush="{DynamicResource Presentation_ControlBorderBrush}" BorderThickness="1"
ItemsSource="{Binding InterfaceSpecification.IOPoints}"
DeleteItemRequestCommand="{Binding DeleteIOPointCommand}" IsEdited="{Binding IsEditable}" >
<pres:OneListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<vw:IOPointDefinitionView Grid.Column="0" />
<vw:IOPointOtherConnectedElementView Grid.Column="1" Margin="20,0"/>
<pres:OneIcon Grid.Column="2" IconBrush="{DynamicResource Icon_DraggableHandleHorizontal}" Margin="8,0" HorizontalAlignment="Right" Visibility="{Binding ElementName=ListBox, Path=IsEdited, Converter={StaticResource OneBooleanToVisibilityConverter}}" />
</Grid>
</DataTemplate>
</pres:OneListBox.ItemTemplate>
</pres:OneListBox>
</pres:OneContentLayout>
<pres:OneTextBox Watermark="Name..." Text="{Binding InterfaceSpecification.Name}" Margin="85,12,0,0"
AcceptsReturn="False" MaxLines="1" Height="22" VerticalAlignment="Top"
HorizontalAlignment="Left" Width="300" Visibility="{Binding IsEditable, Converter={StaticResource OneBooleanToVisibilityConverter}}" />
<pres:OneTextBox Margin="85,3.999,10,3" Text="{Binding InterfaceSpecification.Description}"
Watermark="Description..." Height="66" Grid.Row="1" Visibility="{Binding IsEditable, Converter={StaticResource OneBooleanToVisibilityConverter}}"/>
<pres:OneToggleButton x:Name="Add_Button" Content="Add IO Point" HorizontalAlignment="Right"
VerticalAlignment="Bottom" Margin="0,0,10,0" Grid.Row="2" Width="115" Height="18"
IsChecked="{Binding ElementName=Add_Popover, Path=IsOpen}"
pres:OneTheme.PresentationMode="Inline" Visibility="{Binding IsEditable, Converter={StaticResource OneBooleanToVisibilityConverter}}" />
...
So you basically want pres:OneContentLayout to have a margin of 0 when IsEditable is false and 10 when it's true, right?
You can use a Trigger in a Style to make that work like this:
<pres:OneContentLayout.Style>
<Style TargetType="{x:Type pres:OneContentLayout}">
<!-- Default margin is 0 -->
<Setter Property="Margin" Value="0" />
<Style.Triggers>
<!-- When in edit-mode make margin 10 -->
<DataTrigger Binding="{Binding IsEditable}" Value="True">
<Setter Property="Margin" Value="10" />
</DataTrigger>
</Style.Triggers>
</Style>
</pres:OneContentLayout.Style>

Application Resolution Issue

This is something that I have been skipping and leaving till the end because I can't seem to find the answer and ive looked for so long.
I have a an application inside a Window, and I have built the Application to my screens resolution which is 1600 x 900. If I run the application on a screen with a resolution of 1024 x 768 my whole interface will not scale down.
Example.
Now I know alot of you will be thinking to add Dockpanels etc ... But I have tried to do this. When you change the Resolutions it doesn't work it just fixes the object to one place.
What I want to happen.
If any of you know the solution to this annoying problem, please let me know.
I dont know much about resolutions, only what I have done hours of research on.
EDIT1
Here is some of my XAML:
<DockPanel HorizontalAlignment="Left" Height="236" LastChildFill="False" Margin="380,150,0,0" VerticalAlignment="Top" Width="792">
<DataGrid x:Name="dgFake" VerticalAlignment="Center" Height="236" ItemsSource="{Binding}" Foreground="#FF474747" BorderBrush="#FFBDBDBD" HorizontalGridLinesBrush="{x:Null}" VerticalGridLinesBrush="{x:Null}" CanUserResizeRows="False" ScrollViewer.CanContentScroll="True" Background="#FFEEFAFF" RowBackground="#FFEEFAFF" RowHeaderWidth="0" RowHeight="25" AutoGenerateColumns="False" Width="792" DockPanel.Dock="Left" FontSize="16" TextBlock.TextAlignment="Center" HorizontalContentAlignment="Stretch" SelectionChanged="dgFake_SelectionChanged">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding FFF}" Header="FFF" Visibility="Hidden" CanUserResize="False" CanUserSort="False" CanUserReorder="False" IsReadOnly="True" Width="*" />
<DataGridTextColumn Binding="{Binding EEE}" Header="EEE" CanUserResize="False" CanUserSort="False" CanUserReorder="False" IsReadOnly="True" Width="*" />
<DataGridTextColumn Binding="{Binding GGG}" Header="GGG" CanUserResize="False" CanUserSort="False" CanUserReorder="False" IsReadOnly="True" Width="*"/>
<DataGridTextColumn Binding="{Binding CCC}" Header="CCC" CanUserResize="False" CanUserSort="False" CanUserReorder="False" IsReadOnly="True" Width="*"/>
<DataGridTextColumn Binding="{Binding BBB}" Header="BBB" CanUserResize="False" CanUserSort="False" CanUserReorder="False" IsReadOnly="True" Width="*"/>
<DataGridTextColumn Binding="{Binding AAA}" Header="AAA" CanUserResize="False" CanUserSort="False" CanUserReorder="False" IsReadOnly="True" Width="*"/>
<DataGridTextColumn Binding="{Binding DDD}" Header="DDD" CanUserResize="False" CanUserSort="False" CanUserReorder="False" IsReadOnly="True" TextBlock.TextAlignment="Center" Width="*"/>
</DataGrid.Columns>
<Label x:Name="lblView" Content="Select View ..." HorizontalAlignment="Left" Margin="380,109,0,0" VerticalAlignment="Top" Foreground="#FF474747"/>
<ComboBox x:Name="cmbViews" HorizontalAlignment="Left" Margin="380,124,0,0" VerticalAlignment="Top" Width="162" Text="Select ..." SelectionChanged="cmbView">
<ComboBoxItem Content="Company" Foreground="#FFA2A2A2"/>
<ComboBoxItem Content="Employee" Foreground="#FFA2A2A2"/>
</ComboBox>
I suspect that you have basically designed your WPF application as if it were a WinForms application, setting exact Height and Width values on your UI elements. That is not how we layout UI elements in WPF. If you did do that, then you are correct that putting them in a DockPanel will not fix your problem.
In WPF, we generally use Grid elements to make full use of the available space provided to them. Setting a Grid.ColumnDefinition.Width to Auto and another to * will fill *all of the available width:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <!-- Just big enough for content -->
<ColumnDefinition Width="*" /> <!-- Fills all remaining space -->
</Grid.ColumnDefinitions>
...
<TextBlock Grid.Column="1" Text="I'm in the right cell" />
That's just one example of many... Please read through the Introduction to WPF Layout page from the WPF Tutorial.net website for more information.
The problem you describe is actually quite easy to solve, you simply NEVER use a fixed size for anything. All your panels have to be sized relative to something.
Changing the resolution of a screen is literally the same as changing the size of your window. If it works with a Window.Size of 1024x768 it will work at a 1024x768 resolution.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="384" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<!-- Pretend I'm a logo -->
<Border Height="23" Width="75" HorizontalAlignment="Left" Background="Blue" CornerRadius="5" Padding="3">
<TextBlock Foreground="White">Logo</TextBlock>
</Border>
<WrapPanel Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" Orientation="Horizontal">
<TextBlock Text="About" Margin="6"/>
<TextBlock Text="Home" Margin="6"/>
<TextBlock Text="Help" Margin="6"/>
<TextBlock Text="Settings" Margin="6"/>
</WrapPanel>
<ListBox Grid.Row="1" Grid.Column="0"
BorderThickness="0">
<TextBlock Text="Example" Margin="6"/>
<TextBlock Text="Example" Margin="6"/>
<TextBlock Text="Example" Margin="6"/>
<TextBlock Text="Example" Margin="6"/>
<TextBlock Text="Example" Margin="6"/>
<TextBlock Text="Example" Margin="6"/>
<TextBlock Text="Example" Margin="6"/>
<TextBlock Text="Example" Margin="6"/>
<TextBlock Text="Example" Margin="6"/>
<TextBlock Text="Example" Margin="6"/>
</ListBox>
<Grid Grid.Row="1" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border >
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Red" />
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<TextBlock>I'm a Data Grid</TextBlock>
</Border>
<GridSplitter Grid.Row="1" VerticalAlignment="Top" Height="3"/>
<Border Grid.Row="1" Margin="0,3,0,0">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Blue" />
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<TextBlock>I'm a Data Grid</TextBlock>
</Border>
</Grid>
</Grid>
</Window>
The gradients are there so you can see its working when you resize.
If you've already designed to a fixed resolution then an easy hack is to wrap everything in a ViewBox and give the encapsulating child the same dimensions as the resolution you designed for. So if you designed for 1600 x 900 and your main window contained this:
<Grid>
<TextBlock Text="Big Text" FontSize="100" />
</Grid>
...then replace it with this:
<Viewbox Stretch="Uniform">
<Grid Width="1600" Height="900">
<TextBlock Text="Big Text" FontSize="100" />
</Grid>
</Viewbox>
Then make a mental note to do your UI design properly from day 1 next time.

Categories

Resources