How can I get the height of a Page?, i.e; the height of all elements in the page.
For example, if I have this XAML which makes a Page, how can I get the height at runtime?
<Page x:Class="DialogViews.SomeError"
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="300" d:DesignWidth="400"
Title="SomeMessage">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="50" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Style="{StaticResource ResourceKey=DialogTitleError}">A Problem</Label>
<TextBlock Grid.Row="1" Style="{StaticResource ResourceKey=DialogMsg}">
Some message to user
</TextBlock>
<Label Grid.Row="2" HorizontalAlignment="Right">
<Hyperlink>
Some link for info
</Hyperlink>
</Label>
</Grid>
</Page>
Reason:
I've created a custom Window that will display as a Dialog message to the user, the Window contains a Frame which in-turn contains this Page. I'm trying to fix the height of the Window to that of the Page.
I have tried:
myPage.Height; //NaN
myPage.ActualHeight; //0
If you want to fit the size of the Window to your user control Page, then I would suggest trying the SizeToContent property of Window.
<Window x:Class "MyNameSpace.MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
SizeToContent="Height" />
Height - Specifies that a window will automatically set its height to fit the height of its content, but not the width.
Edit: This will stretch your Window to fit the Frame, which hopefully is set to change with the widths/heights of your Page.
Are you looking for
SystemParameters.FixedFrameVerticalBorderWidth
SystemParameters.FixedFrameHorizontalBorderHeight
SystemParameters.WindowCaptionHeight
Please check this msdn link
Try with
this.Height;<br/>
this.Width;
Related
Consider the following code-behind for displaying a child window after clicking a button in the Main Window. The desired result is to have the child window placement show up just to the right of the menu button, in-line with the top of the menu button. (So the window shows right next to the control that activated it.)
private void btnMenu2_Click(object sender, RoutedEventArgs e)
{
var menu2 = new Menu2Window();
//var winLocation = this.btnMenu2.TranslatePoint(new Point(0, 0), Application.Current.MainWindow);
//var winLocation = this.btnMenu2.TranslatePoint(new Point(0, 0), this.spLeftMenu);
//var winLocation = this.spLeftMenu.TranslatePoint(new Point(0, 0), this.btnMenu2);
var objLocation = this.spLeftMenu.TranslatePoint(new Point(0, 0), this.spLeftMenu);
var scnLocation = this.btnMenu2.PointToScreen(objLocation);
//menu2.Left = scnLocation.X + btnMenu2.Width;
menu2.Left = scnLocation.X + 50; // <- Why does this work but using btnMenu2.Width causes placement to be all over the place???
menu2.Top = scnLocation.Y;
menu2.ShowDialog();
}
The code as presented does work in the fashion needed, however I don't like using hard-coded values or magic numbers in code.
If you comment out the line with the hard-coded control width value (50) and un-comment the line using the button's width property, subsequent execution results in the menu window displaying in a sequence of locations that defy logic. It appears that it is getting a value from a random number generator rather than the control's width. I do see a pattern when its run several times, but getting 4 or 5 different locations because of a variation in property value responses each time the code is executed is quite frustrating.
What would be the RIGHT or correct approach here? How do I get a reliable value back from a WPF control property or am I asking too much?
XAML of Main Window:
<Window x:Class="LocateTest.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:LocateTest"
mc:Ignorable="d"
Background="DarkGray"
Title="MainWindow" Height="400" Width="750">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel x:Name="spLeftMenu"
DataContext="MainWindow"
Orientation="Vertical"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Height="325" Width="50">
<Button Content="B1" Height="50" Width="50"/>
<Button x:Name="btnMenu2"
Content="B2"
Height="50"
Click="btnMenu2_Click"/>
<Button Content="B3" Height="50"/>
</StackPanel>
</Grid>
</Window>
XAML of Menu2 window:
<Window x:Class="LocateTest.Menu2Window"
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:LocateTest"
mc:Ignorable="d"
WindowStyle="None"
AllowsTransparency="True"
WindowStartupLocation="Manual"
Height="150" Width="280">
<Window.Background>
<SolidColorBrush Opacity="0.5" Color="Black"></SolidColorBrush>
</Window.Background>
<Grid>
<Button x:Name="btnClose"
Click="btnClose_Click"
Width="25"
Height="25"
Content="X"
Background="Black"
Foreground="Red" Margin="245,10,10,115">
</Button>
</Grid>
</Window>```
Since you don't explicitly set the width of btnMenu2, the value of its Width property will be double.NaN. Note that the Width value is not the actual width, but the requested width. Use the ActualWidth proeprty instead:
menu2.Left = scnLocation.X + btnMenu2.ActualWidth;
What about using Popup instead? You can put all you want on a Popup control instead of a window and set its StaysOpen property to true to make the user close it automatically through close button or whatever.
let's say I have a grid with 4 columns. Every column takes the same amount of width
-> 100% / 4cols = 25%.
The 3rd column has a TextBlock or any other control in it. Now, when I resize the Width of the Window and the column gets to a minimum value, I want the TextBlock to use ColumnSpan="2" else the TextBlock would be too small. I hope you guys understand what I mean. I tried so many things but I didn't even come close to what I want because I'm pretty new to WPF. For example setting the minWidth so it doesn't get too small doesn't work because at some point the controls will still be hidden inside the grid column. I don't have any useful xaml for you, unless you just want the grid layout. Maybe a Grid is not the right thing i want? The other layouts didn't seem right for this purpose. Any help is appreciated.
You could handle the SizeChanged event of the Grid or the window and programmaticlly set the Grid.ColumnSpan attached property of the TextBlock whenever the grid/window shrinks below a pre-defined minimum width. Please refer to the following sample code.
private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
{
const double MinWidth = 200;
Grid grid = (Grid)sender;
if (grid.ActualWidth < MinWidth)
Grid.SetColumnSpan(textBlock, 2);
else
Grid.SetColumnSpan(textBlock, 1);
}
XAML:
<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"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="300">
<Grid SizeChanged="Grid_SizeChanged">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25*" />
<ColumnDefinition Width="25*" />
<ColumnDefinition Width="25*" />
<ColumnDefinition Width="25*" />
</Grid.ColumnDefinitions>
<TextBlock Background="Yellow" Text="1" />
<TextBlock Background="Green" Text="2" Grid.Column="1" />
<TextBlock Background="Red" Text="4" Grid.Column="3" />
<TextBlock x:Name="textBlock" Background="Blue" Text="3" Grid.Column="2" Grid.ColumnSpan="2" />
</Grid>
</Window>
If you decrease the width of the window, the blue TextBlock streches across the third and fourth columns.
I'm having a problem with determining which element is responsible for a size misalignment. Here is a picture to illustrate it: click here to see it
The light grey area is the element size which I am trying to change, but cannot. The overall area is a User Control, the area inside the Tab is a WPF (as an element Host). I've tried changing both, but with no effect on the grey area (the other tabs are also affected by this). Here is the code for the hosted element (WPF):
<UserControl x:Class="SlideAnalyzer.DisplayAnalysis"
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"
xmlns:local="clr-namespace:SlideAnalyzer"
mc:Ignorable="d"
d:DesignHeight="150.8" d:DesignWidth="201.2">
<Grid Name="displayGrid" Height="64" VerticalAlignment="Bottom" HorizontalAlignment="Center" Width="160" Margin="10,0,31.6,9.4" RenderTransformOrigin="0.496,0.94">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Expander x:Name="expander" Grid.Row="0" Header="Titel zu lang" HorizontalAlignment="Left" VerticalAlignment="Top" Width="180" Background="Red" Margin="-10,-56,0,0">
<Grid Background="AliceBlue">
<TextBlock TextWrapping="Wrap"
Margin="5"><Run Text="This is some text content."/></TextBlock>
</Grid>
</Expander>
</Grid>
The host itself is a normal User Control. I cannot seem to get the right size of the hosted element so that the preview really reflects reality (because when I run the Add-In, the size of the WPF differs)
I tried changing the Properties of the UserControl and I found that AutoSize has a big impact when True (by default False)
Thanks!
I have a WPF Window which contains a Grid. It's set up to look like a Checkers board, so I need the squares of the grid to stay square when the window is resized.
I've tried many things but nothing seems to work. I hope it's just a matter of getting the right attribute, and not something complicated, but I need it to resize proportionally either way.
I'm also not sure if this should happen in the Grid or in the Window. I would assume the Window because that's the controller for resizing, but I could be wrong.
Any suggestions?
xaml for Window:
<Window x:Class="TicTacToeClient.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TicTacToeClient"
Title="Mini-Checkers V1.1" Height="600" Width="600"
MinHeight="200" MinWidth="200" MaxHeight="600" MaxWidth="600" >
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="Game">
<MenuItem Header="Set Ip Address" Name="IPAddressMenuItem"/>
<MenuItem Header="Set Name" Name="SetNameMenuItem"/>
</MenuItem>
</Menu>
<TextBlock DockPanel.Dock="Bottom" Text ="Status: " Name="GameStatusBar" />
<local:TicTacToeBoard x:Name="GameBoard" />
</DockPanel>
xaml for Grid:
<UserControl x:Class="TicTacToeClient.TicTacToeBoard"
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="600">
<Grid Name="MainGrid">
<Grid.RowDefinitions>
....
I would suggest DataBinding the Width of your Grid to the Height (or vice-versa). This will make sure that it always grows proportionally. Something as simple as this should work:
<Grid x:Name="Checkerboard" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Width="{Binding RelativeSource={RelativeSource Self}} Path=ActualHeight}">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!-- Grid Contents -->
</Grid>
And if you want your cells to all remain square, just make sure they're all * sized, so they will be spread out equally.
Alternatively, you can put yor grid inside a Viewbox with Stretch="Uniform"
You can try enclosing yourGameBoard in a ViewBox with Stretch Property set to Uniform and StretchDirection set to Both. like this. It wont keep the Form's Aspect ratio uniform but will keep your GameBoard Proportions Uniform.
<Viewbox Stretch="Uniform" StretchDirection="Both">
<local:TicTacToeBoard x:Name="GameBoard" />
</Viewbox>
Everything about my layout will flow with the resizing of the main window. The problem I'm facing is that as you can see, the datagrid goes off the screen. If you maximize the window, the datagrid will resize with the window, but continue to go off the screen. How do I get it to maintain its margin of 20 with it's parent grid?
<Grid>
<StackPanel Orientation="Vertical">
<TextBox Height="170" Name="txtSQL" VerticalAlignment="Top" AcceptsReturn="True" TextWrapping="Wrap" Margin="20"/>
<Button Content="Run!" Height="23" HorizontalAlignment="Left" Name="btnRun" VerticalAlignment="Top" Margin="20,0,0,0" Width="75" Click="btnRun_Click" />
<Grid>
<my:DataGrid Name="dgResults" VerticalAlignment="Top" Margin="20" />
</Grid>
</StackPanel>
</Grid>
UPDATE:
Just to be more specific. The effect I'm trying to accomplish here is this:
When the window first loads, you are presented with a blank datagrid, so it's only about 15 pixels high. When you run the query, it will populate the datagrid by reassigning the itemssource. As of now, when you do that, if the data exceeds the window size, it will go off the bottom of the screen. I need it to only expand to the bottom of the window then enable the scrollbar. I can do this just by wrapping it in a scrollviewer im sure. However, when the window is resized, the datagrid needs to resize with it.
I'm wondering if the setup might have something to do with it. The form is actually a wpf page being displayed in a frame.
UPDATE:
<Page x:Class="Hold_Database___Prototype_1.Views.SQL"
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="304" d:DesignWidth="732"
Title="SQL" xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit" AllowDrop="True">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="23" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox Height="170" Name="txtSQL" VerticalAlignment="Top" AcceptsReturn="True" TextWrapping="Wrap" Margin="20" Grid.Row="0"/>
<Button Content="Run!" Height="23" HorizontalAlignment="Left" Name="btnRun" VerticalAlignment="Top"
Margin="20,0,0,0" Width="75" Grid.Row="1" Click="btnRun_Click" />
<DockPanel Grid.Row="2">
<my:DataGrid Name="dgResults" Margin="20" />
</DockPanel>
</Grid>
</Page>
What is the dock panel for in this example?
Try putting the DataGrid directly in the cell with no stackpanel. If you are setting the button height then set set grid to auto.
Also, why give so much space to the text?
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox Height="170" Name="txtSQL" VerticalAlignment="Top" AcceptsReturn="True" TextWrapping="Wrap" Margin="20" Grid.Row="0"/>
<Button Content="Run!" Height="23" HorizontalAlignment="Left" Name="btnRun" VerticalAlignment="Top"
Margin="20,0,0,0" Width="75" Grid.Row="1" Click="btnRun_Click" />
<my:DataGrid Grid.Row="2" <my:DataGrid Name="dgResults" Margin="20" />
Then also set HorizontalAlignment, VerticleAlignment, HorizontalContentAlignment, and VerticalContentAlignment = stretch
Your Grid is drawn off screen without a scroll bar because you are using a StackPanel. Care must be taken when using StackPanel - it is the most simplistic of all WPF Panel derived classes since its MeasureOverride calls Measure for all of its children with a size of double.PositiveInifity regardless of how much space the panel actually has available. Even a ScrollViewer will not help you with a StackPanel (the ScrollBar will be shown, but you won't be able to move it).
For example, consider a Window 350 in height and width, and a single Button as its content which is 500 in both height and width:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="350">
<StackPanel>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Button Content="Hello" Height="500" Width="500" />
</ScrollViewer>
</StackPanel>
</Window>
Similar to your example, the Button here is drawn off screen in both the vertical and horizontal directions and a non-functional scroll bar will be present. If we change the panel to one which respects the size of its given area (e.g. DockPanel):
<Window x:Class="WpfApplication2.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">
<DockPanel>
<ScrollViewer>
<Button Content="Hello" Height="500" />
</ScrollViewer>
</DockPanel>
</Window>
then scroll bars appear which are functional and hence allow the content off screen to be shown by scrolling.
Hope this helps!
What I have done was do define the horizontal and vertical alignments to "Stretch" respectively at the control you want (your DataGrid) to take up the size based on the window being resized.