Strange white box covering controls - wpf

In the Designer everything looks alright but in Debbuging a weird white rectangle covers a part of it (If I don't set any Margin in the Button, It looks fine).
Designer
While Debugging
<Window x:Class="MyProgram.MainWindow" ResizeMode="NoResize"
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:MyProgram"
mc:Ignorable="d"
Title="MyProgram" Height="450" Width="650">
<Grid>
<Label Content="Things:" HorizontalAlignment="Left" Margin="0,7,0,0" VerticalAlignment="Top" FontSize="22"/>
<Button Height="28" Width="180" Background="Transparent" BorderThickness="0" Margin="454,15,10,378" >
<StackPanel Orientation="Horizontal">
<Image Source="Resources/addpackage2.png" Width="35" />
<TextBlock Text="Add" Margin="3,0,3,0" FontSize="18" />
</StackPanel>
</Button>
</Grid>
I'm doing something wrong?

The margin on your button Margin="454,15,10,378" is constricting the space available for the button. If you make the make the window larger, you will see the whole button.
Edit
There are different ways to organize a layout in XAML, but usually a grid is a good choice.
This is one way you could write it.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Things:" HorizontalAlignment="Left" Margin="7" VerticalAlignment="Top" FontSize="22"/>
<Button Grid.Row="0" Grid.Column="1" Height="28" Width="180" Background="Transparent" BorderThickness="0" >
<StackPanel Orientation="Horizontal">
<Image Source="Resources/addpackage2.png" Width="35" />
<TextBlock Text="Add" Margin="3,0,3,0" FontSize="18" />
</StackPanel>
</Button>
</Grid>
I have added row and column definitions to the grid. In this case two rows and two columns.
The top row is sized automatically according to its content. The second row fills the remaining space.
Similarly, the right hand column is sized automatically according to its content and the left hand column fills the remaining space.
This is just an example. You might want to define a different layout. I presume that the bottom of the screen will not always be white space.
Having defined the rows and columns, you can assign the individual controls to the cells in the grid, by specifying the Grid.Row and Grid.Column properties.
I have placed your label in row 0, column 0 and I have placed the button in row 0 column 1.
Very important, is that I have removed the Margin definition from the button. This kind of positioning controls is, in my opinion, always an error.
I think that the layout is more or less as you wanted.

Related

xaml layout introduction for Qt programmer

I am used to Qt and its Qt Designer.
XAML with its layout controls 'grid' and 'StackPanel' are somehow similar, but I still miss or do not find some of the most common properties of designs in Qt. Since I am completely new to XAML I would like to know the answers or further available documentations.
For example I want to add 2 elements (lets say buttons) either horizontal or vertical with their default height and a minimum height and minimum width. If aligned horizontal they shall be pushed to the left side and the remaining side on the right should be free. That means that the size of the buttons does not increase if the windows size is increased. In Qt this is realized by a grid in combination with a spacer (see for example this tutorial for an example).
My first XAML is far away from what I expect. The definition of RowDefinition is copied from a tutorial. However I do not understand its meaning...
<Window x:Class="SpectrumViewer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Spectrum Viewer" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Margin="8" VerticalAlignment="Top">
<Button MinWidth="75" MaxHeight="23" Margin="10" HorizontalAlignment="Left" Width="100" Name="buttonTest">test</Button>
<TextBox MinWidth="75" MaxHeight="23" Margin="10" HorizontalAlignment="Left" Width="150" Name="textBoxValue"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="8" >
<Button MinWidth="75" MaxHeight="23" Margin="10" HorizontalAlignment="Left" Width="100" Name="button1">button 1</Button>
<Button MinWidth="75" MaxHeight="23" Margin="10" HorizontalAlignment="Left" Width="100" Name="button2">button 2</Button>
</StackPanel>
</Grid>
</Window>
The next image shows that the elements are pushed to the left side, but the two stacked panels above each other are not pushed to the top. If I set them both with VerticalAlignment="Top" they overlap which is also wrong.
If I resize the window one can see that the elements are not resized and that the second StackPanel overlaps with the first:
Instead the elements should be resized to the minimum width and any further resizing of the windows should be prohibited.
The first problem of the two stack panels overlapping when you set both VerticalAlignment to Top is because since you haven't specified in which Grid.Row they should be, the default would be both in Grid.Row = 0. Specify the row index and they won't overlap :
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="8" VerticalAlignment="Top">
....
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="8" VerticalAlignment="Top">
....
</StackPanel>
There is no way the window would stop resizing when the minimum size of the buttons is reached. You could set the MinWidth of the Grid and ask the window to stop right there :
<Window x:Class="SpectrumViewer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Spectrum Viewer" Height="350" Width="525"
MinWidth="{Binding RelativeSource={RelativeSource Self}, Path=Content.MinWidth}">
<Grid MinWidth="350">
.......
</Grid>
</Window>
Or set the MinWidth of the Window itself :)

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>

How can I prevent the grid splitter from resizing a column outside of the window bounds?

I have the XAML shown below (for example). If you drag the grid splitter as far as it goes to the left, and keep dragging the mouse, the right-hand column will grow in size outside the bounds of the window - obviously not what I want.
The problem is that I can't set a hard MaxWidth on the right-hand column because the user can resize the window, thus increasing the available space for that column.
So far I think I need to bind the MaxWidth of the right-hand column to something like the window's client area minus the MinWidth of the left plus the width of the splitter column. But I'd like to avoid that if possible. Thoughts?
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="450"
Height="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MinWidth="100" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="200" MinWidth="200" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Button>Monkey</Button>
</Grid>
<GridSplitter Grid.Column="1" Width="7" ResizeBehavior="PreviousAndNext" />
<Grid Grid.Column="2" Margin="4">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<GroupBox Grid.Row="0" Header="Spaghetti" Margin="0, 0, 0, 5">
<ComboBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch">Noodles</ComboBox>
</GroupBox>
<Expander Grid.Row="1" Header="Batman" IsExpanded="True" Margin="0, 0, 0, 5">
<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch">Batman!</Button>
</Expander>
</Grid>
</Grid>
</Window>
I'm having the same problem. Maybe this will be a partial answer. I bound the MaxWidth of the column I'm expanding to the ActualWidth of its grid. The goal being that the splitter never exceed the size of its grid. The binding works correctly but it's not achieving the goal because once my grid splitter gets to the edge of the grid, the grid starts resizing larger as I drag the splitter. If we can make the grid not resize with the splitter, this should work.

How to stretch the controls as per the page size in wpf

I have a listview of width set to Auto. When I run the windows app, it opens in normal size(not maximized). But when I maximize the window, the listview's width will be same and the space to its right is empty.
normal size
|_________________________|
Maximized
|_________________________|...........
even though the window is now in full screen occupied.
Please guide me in workin on this.
Thanks
Ramm
StackPanel, by design, does not care about visual space. It aims to take up the smallest amount of space possible. You can leave the innermost StackPanel that wraps the radio buttons in place, but your outer layout containers should be changed to Grid or, as in my example below, DockPanel:
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="445" Width="515">
<DockPanel Name="spDataFlow" Margin="0,45,0,0" >
<DockPanel x:Name="stkPnlDataFlow" VerticalAlignment="Top">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
</Grid>
<StackPanel Grid.Row="1" Background="Red" Margin="20,15,0,0" Orientation="Horizontal" VerticalAlignment="Center" >
<RadioButton Name="rdbtnUploadData" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="12" Foreground="White" Content="Upload Data" IsEnabled="True" CommandParameter="UploadAll"/>
<RadioButton Name="rdbtnDownloadData" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="12" Foreground="White" Content="Download Data" Margin="20,0" CommandParameter="DownloadAll"/>
<RadioButton Name="rdbtnUploadSelected" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="12" Foreground="White" Content="Update Data" Margin="10,0" CommandParameter="UpdateSelected"/>
</StackPanel>
</DockPanel>
</DockPanel>
</Window>
Well, I believe that by default the ListView control automatically fills all available space so it is very strange that have such an issue. Could you paste your code?

Centering a WPF control

I have a window where I add a new UserControl to (with an image), I simply want to center the control in the middle of the screen (both vertically and horizontally). I can only get the vertical one to work. I'm gonna swap content in the DockPanel from my CodeBehind and want to show this startup screen before I start doing my slideshow UI, this means that the content is set from the CodeBehind.
My Window:
<Window x:Class="GreenWebPlayerWPF.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="512" Width="853" WindowStyle="None" WindowState="Maximized" WindowStartupLocation="CenterScreen">
<DockPanel Width="Auto" Height="Auto" Name="TransitionContainer" Background="Black" Margin="0" LastChildFill="True"></DockPanel>
</Window>
My UserControl:
<UserControl x:Class="GreenWebPlayerWPF.FrontPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DockPanel Background="Black">
<Image Name="image1" Stretch="None" Source="/GreenWebPlayerWPF;component/gw.png" />
</DockPanel>
</UserControl>
Please note that I'm using maximized/full screen.
Use a Grid:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Replace with your UserControl -->
<Button Content="Foo" Grid.Column="1" Grid.Row="1"/>
</Grid>
You can dock it inside your DockPanel (if you must have a DockPanel there) to stretch. And, of course, while the above is all markup, you can just as easily create such a grid from code.
I keep running into this problem when trying to center elements on the page.
The problem with the StackPanel is that HorizontalAlignment has no effect when the Orientation is Horizontal and VerticalAlignment no effect when Orientation is Vertical. So you keep banging your head trying to set values with no effect. It is not illogical that it works this way but it would be good if this was reported as an error.
The solution I found is to have two imbricated StackPanels one centered horizontally and the other vertically as shown below. Finding the size of the parent is needed to size the intermediate panel otherwise it would be flat and its content hidden - an absolute value would work as well. Although not a panacea itis a bit less verbose than using a grid.
<StackPanel Background="Bisque" Orientation="Vertical" Width="300" Height="300" >
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal"
Height="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=StackPanel}, Path=ActualHeight}">
<StackPanel VerticalAlignment="Center" Width="200" Height="60" Background="Blue">
</StackPanel>
</StackPanel>
</StackPanel>
It's quite an old one, but centring a control is now as simple as:
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Height="350" Width="600">
<TextBox />
</StackPanel>
</Grid>

Resources