I'm an experienced developer, but new to C# and the Windows Runtime. I'm trying to create a custom UserControl (a specialized button) that can be dynamically sized. My button should have three rows of text on it (Top, Middle, Bottom) which are given proportional sizes (1*, 3*, 1*). I want the textboxes to fill their given space in the grid. i.e. If the button is 500x200, then the internal TextBoxes would all be 200 wide, the Top one would be 100 pixels tall, the Middle would be 300 tall, and the bottom would be 100 tall. If the button is 700x300, Top=140, Middle=420, Bottom=140.
I created a Grid with proportionally sized Rows and it behaves the way I want, but I don't know how to get the child elements in the grid to fill their space in the grid cell.
<UserControl
x:Class="DynamicButtons.DynamicButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DynamicButtons"
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 Background="SlateGray">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="3*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<TextBox Text="Top" Grid.Row="0" Margin="0,0,0,0" TextAlignment="Center" />
<TextBox Text="Middle" Grid.Row="1" Margin="0,0,0,0" TextAlignment="Center" />
<TextBox Text="Bottom" Grid.Row="2" Height="Auto" Margin="0,0,0,0" TextAlignment="Center" />
</Grid>
</UserControl>
If you add VerticalAlignment="Stretch" to your TextBox definitions, they'll fill the vertical space.
Related
I want to create a content dialog with full width and height but i have a problem with set the width for all screen sizes and keep the button on the bottom
and Here's my code
<ContentDialog
x:Class="app.Content_Dialog.WhatsNew"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:app.Pages"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Name="dialog2" Height="Auto" Width="Auto" FullSizeDesired = "True" MaxWidth="600">
<Grid Height="800" Width="Auto">
<Grid VerticalAlignment="Stretch" Margin="-24,0,0,165" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<!-- Take as much as needed -->
<RowDefinition Height="Auto" />
<!-- Take exactly 20 DIP -->
<RowDefinition Height="*" />
<!-- Take all the rest -->
</Grid.RowDefinitions>
<Button x:Name="close" VerticalAlignment="Bottom" Content="close" Height="102" Width="374" HorizontalAlignment="Right" Grid.Row="2"/>
</Grid>
</Grid>
I'm trying to create something like this content dialog on MSPoweruser app
Here's a picture for it
You shouldn't define a Close Button inside your content Grid, instead, use the CloseButton that's built within the ContentDialog itself.
So just remove the Button and the Margin on your Grid, and
if you only target Windows 10 build 15063 and onward
add CloseButtonText="Close" to your ContentDialog;
if you target anything before 15063
add SecondaryButtonText="Close" instead.
If you want the CloseButton to take up the space horizontally, you need to apply a custom style to your ContentDialog, locate the container of the Buttons and remove its column definitions.
Let's say I have XAML code like this:
<UserControl x:Class="Sample.MyClass"
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="220" d:DesignWidth="750">
<ScrollViewer Width="730" Height="150" CanContentScroll="True" HorizontalScrollBarVisibility="Visible">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="680" />
</Grid.ColumnDefinitions>
<TextBox Width="50" Height="200" Grid.Row="0" Grid.Column="0" />
<TextBox Width="680" Height="200" Grid.Row="0" Grid.Column="1" />
</Grid>
</ScrollViewer>
</UserControl>
Now when I scroll to the right I'd like the first TextBox to be fully visible. In other words - I would like the horizontal scrolling (only horizontal scrolling) to apply only to the second TextBox and vertical scrolling to aplly to both. I can't put the first one outside of the ScrollViewer because then vertical scrolling would not work on it.
To give you a more real-life example:
In VisualStudio you have the text area where you can enter code. And on the left side there's a panel showing line numbers and code folding. If you scroll the text area vertically also the left panel is scrolling down or up. When you scroll the text area horizontally, only the text area is affected by it.
You can try to modify XAML as following:
<UserControl x:Class="Sample.MyClass"
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="220" d:DesignWidth="750">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="680" />
</Grid.ColumnDefinitions>
<ScrollViewer Grid.Row="0" Grid.Column="0"
CanContentScroll="True"
VerticalScrollBarVisibility="Visible"
HorizontalAlignment="Stretch">
<TextBox />
</ScrollViewer>
<ScrollViewer Grid.Row="0" Grid.Column="1"
CanContentScroll="True"
VerticalScrollBarVisibility="Visible"
HorizontalScrollBarVisibility="Visible"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<TextBox />
</ScrollViewer>
</Grid>
</UserControl>
Hope this may help.
I think what you want to do is svnc 2 scroll viewers,
You can do it with a little code behind voodoo, check this out
Synchronized scrolling of two ScrollViewers whenever any one is scrolled in wpf
I have created a WPF application that generate tiles in the second row of grid. What i'm trying to achieve is to keep rendering tiles in the second row without showing the vertical scroll bar, until unless the height of WPF application crosses the resolution of user screen.
<Window x:Class="ABC.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ABC Installation" MinWidth="620" SizeToContent="WidthAndHeight" AllowsTransparency="True" WindowStyle="None" Loaded="MainWindow_loaded" MinHeight="600" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition Height="56" />
<RowDefinition Height="Auto" ScrollViewer.IsDeferredScrollingEnabled="True" />
<RowDefinition Height="94"/>
</Grid.RowDefinitions>
</Grid>
<ScrollViewer Name="productsOuterScroll" Grid.Row="2" HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Auto" Grid.RowSpan="1" >
<StackPanel x:Name="FormStackPanel">
</StackPanel>
</ScrollViewer>
This code renders all the tiles exceeding the user screen window height without a vertical scroll bar.
Any idea how to do this? Any help would be appreciated.
If you want the content to scroll, remove the Height from the RowDefinition of the row that you are adding content to, and put the content inside the ScrollViewer.
Your window might be sizing correctly to the vertical resolution of the screen, but if it's displayed in the center of the screen, it will exceed the height. You can set the startup location to top of the screen with:
WindowStartupLocation="Manual" Top="0"
If the window height is too high, you might want to set maximum height for your window.
I figured out the mistake. Only two things needed to be done.
remove the height attribute from row definition so it should look like this
<Window x:Class="ABC.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ABC Installation" MinWidth="620" SizeToContent="WidthAndHeight" AllowsTransparency="True" WindowStyle="None" Loaded="MainWindow_loaded" MinHeight="600" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition Height="56" />
<RowDefinition ScrollViewer.IsDeferredScrollingEnabled="True" />
<RowDefinition Height="94"/>
</Grid.RowDefinitions>
<ScrollViewer Name="productsOuterScroll" Grid.Row="2" HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Auto" Grid.RowSpan="1" >
<StackPanel x:Name="FormStackPanel">
</StackPanel>
</ScrollViewer>
</Grid>
Setting the max Height dynamically according to the users primary screen height in .cs file
double userheightscreen = System.Windows.SystemParameters.PrimaryScreenHeight;
this.MaxHeight = userheightscreen - 100;
PS: "-100" is just to leave some space on top and bottom of the screen.
I'm trying to build a layout that would fix the bottom of two rows to be always visible. the problem is, the content of the bottom row has to be at the top, which makes it difficult to use a dockpanel. here's a short overview:
here is a link with pictures for all the windows:
(sorry about that, but stackoverflow won't let me post images yet..)
the first window is how it's supposed to look when there's plenty space available, the bottom (blue) sticks to the top (red).
the code looks like this:
<DockPanel>
<Grid VerticalAlignment="Top"
Background="Red"
DockPanel.Dock="Top">
<Grid Height="100" />
</Grid>
<Grid Height="20"
Background="Blue"
VerticalAlignment="Top"
DockPanel.Dock="Bottom" />
</DockPanel>
but when I size the window so the second row doesn't fit anymore, the second row is not fixed and will be invisible when the window is too small: window 2
so what I want is something like this:
<DockPanel>
<Grid Height="20"
Background="Blue"
DockPanel.Dock="Bottom" />
<Grid VerticalAlignment="Top"
Background="Red"
DockPanel.Dock="Top">
<Grid Height="100" />
</Grid>
</DockPanel>
which gives me the following with enough space available: window 3
and this when I resize the window: window 4
the bottom is fixed. The problem here is, when there's too much space, the second row doesn't stick to the top, but to the bottom like in the third picture.
I've played around with DockPanel.LastChildFill and the child order in a dockpanel. I've tried various layouts using one or more grids but couldn't get it to work.
how would I go about doing this?
edit:
#publicgk:you're right, the second window was the wrong one, I updated the link.
Moreover, I'll try to explain myself a little better.
Considering the first row is completely red, and the second row is the rest (blue and white together). Then the first code sample gives me the first and the second window: While the content of the second row (the blue part) is at the top (window1, which is what I want), the second row is not fixed/always visible when i resize the window (window 2).
The second code sample produces window 3 and 4, while the content is at the bottom of the second row when the window is big enough (window 3, not what I want), the second row is visible even when I resize the window (window 4, that's what i want), so the second row is overlapping the first.
To sum it up i need the rows to behave like window 1 when there's enough space, and like window 4 when there's not.
Edit2: I forgot to mention, the first row is supposed to hold contents, of which the size is unknown and variable, so using a grid and setting height or maxheight of the first row won't work. the height of the second row however is known and may be set directly.
here's a sample, which shows this problem:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
Title="MainWindow"
Width="525"
Height="350">
<Window.Resources>
<local:RandomHeightConverter x:Key="RandomHeightConverter"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100*" MaxHeight="100"/>
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="Red" Height="{Binding Converter={StaticResource RandomHeightConverter}}" />
<Grid Grid.Row="1" Background="Blue" />
</Grid>
public class RandomHeightConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return new Random().Next(20, 100);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
that would produce results like this:
variable first row problem
Not sure if you can do this layout using DockPanel, but you may be able to use Grid to do this sort of layout.
Something like this replicates what you are trying to do
<Window x:Class="WpfApplication9.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication9"
Title="MainWindow" Height="209" Width="525" Name="UI">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100*" MaxHeight="100" />
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="Red" />
<Grid Grid.Row="1" Background="Blue" />
</Grid>
</Window>
Or bind the RowDefinition sizes to the contents you want to show, so in the below example the top sction will size to fix its contents but can shrink, the bottom row is fixed size to the bottom content and will overlap when the window is sized smaller than the Top row.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" MaxHeight="{Binding ElementName=topContent, Path=ActualHeight, Mode=OneTime}" />
<RowDefinition Height="{Binding ElementName=bottomContent, Path=ActualHeight,Mode=OneTime}" />
</Grid.RowDefinitions>
<Grid x:Name="topContent" Grid.Row="0" >
<!--your top content-->
<Grid Height="200" Background="Red" />
</Grid>
<Grid Grid.Row="1" >
<!--your bottom content-->
<Grid x:Name="bottomContent" VerticalAlignment="Top" Height="20" Background="Blue" />
</Grid>
</Grid>
Result:
I have the following wpf layout given to me by my employer. It makes use of multiple nested stack panels.
I'm trying to anchor a data grid which is inside a stack panel a fixed distance away from the main window's four corners. And whenever the grid contains data of which some of it is hidden because of the parent window's size, it is supposed to display scroll bars which must disappear if not needed.
I set the data grid's and the stack panel's width to Auto so that it fills the width and that makes the horizontal and vertical scroll bars behave as i want them to. BUT the grid doesn't have the required height.
But when i try to set the data grid's height property to auto both the horizontal and vertical scroll bars disappear resulting in hidden data.
I tried setting the data grids height property to a fixed size and updating it whenever the window is resized but the scroll bars are still hidden how can i fix this?
<UserControl x:Class="WpfApplication1.UserControl1"
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="441" d:DesignWidth="300">
<Grid>
<StackPanel Margin="0" Name="stackPanel1">
<ListBox Height="100" Name="listBox1" Width="253" />
<Button Content="Button" Height="23" Name="button1" Width="256" Click="button1_Click" />
<StackPanel Name="stackPanel2">
<StackPanel Height="34" Name="stackPanel3" Width="249" />
<DataGrid AutoGenerateColumns="False" Name="dataGrid1" Height="282" />
</StackPanel>
</StackPanel>
</Grid>
</UserControl>
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:WpfApplication1" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="WpfApplication1.MainWindow"
Title="MainWindow" Height="502" Width="525" StateChanged="Window_StateChanged">
<Grid Margin="0">
<my:UserControl1 x:Name="userControl11" Loaded="userControl11_Loaded" />
</Grid>
</Window>
I don't understand all this StackPanel inside StackPanel stuff. You should simply use Grid for your layout:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" Height="100" Name="listBox1" Width="253" />
<Button Grid.Row="1" Content="Button" Height="23" Name="button1" Width="256" />
<StackPanel Grid.Row="2" Height="34" Name="stackPanel3" Width="249" />
<DataGrid Grid.Row="3" AutoGenerateColumns="False" Name="dataGrid1" />
</Grid>
And having an empty StackPanel stackPanel3 as spaceholder seems awkward. Thats what WPF elements have a Margin property for.
When you put items into a vertical StackPanel they like to pretend they have infinite vertical space. Switch over to specifying rows on your Grid, and place your DataGrid in one of those rows. When it's inside a Grid it knows how much space it has available and should show the scrollbars appropriately.