SizeToContent Fills Screen with RichTextBox and FlowDocumentScrollViewer - c#

I'm trying to show a FlowDocument in a WPF form and have tried both RichTextBox and FlowDocumentScrollViewer. I also require that the window resizes to be able to show all text.
Unfortunately, when I set SizeToContent="WidthAndHeight" for the Window itself, no matter what content I put in the FlowDocument, the window expands to the full width of all my displays! The height seems to resize fine, however.
Anyone know how to get it to resize properly? Looked all over and cannot figure out how to get this going...
XAML below:
<Window x:Class="CustomControls.SecureConfirmationDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SecureConfirmationDialog"
MinHeight="120" MinWidth="200"
Height="120" Width="300"
ResizeMode="NoResize"
SizeToContent="WidthAndHeight"
WindowStyle="ToolWindow"
Loaded="Window_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<FlowDocumentScrollViewer Name="flowMsg" Grid.Row="0" Grid.ColumnSpan="3" Margin="3" IsToolBarVisible="False" ScrollViewer.VerticalScrollBarVisibility="Hidden" />
<TextBox Name="txtConfirm" Grid.Row="1" Grid.Column="0" Text="Testing" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="3" />
<Button Name="btnOK" Grid.Row="1" Grid.Column="1" Content="OK" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="3" Width="50" Click="btnOK_Click" />
<Button Name="btnCancel" Grid.Row="1" Grid.Column="2" Content="Cancel" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="3" Width="50" Click="btnCancel_Click" />
</Grid>
</Window>

SizeToContent only "works" if the content is actually bounded, in this case however the Grid, which is the content of Window, has no size restrictions so it will try to get all the space it can get, the window responds by giving it as much space as fits the screen.
If you want to prevent this you would need to make the container for your document to size to their content which might be impossible if the document does not have any bounds itself and also behaves in a give-me-all-you-have manner.

Related

SizeToContent not respecting SharedSizeGroups

Using a window's SizeToContent="WidthAndHeight" property seems to break a grid's column and row definition's property SharedSizeGroup.
<Window x:Class="SizeTest.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"
SizeToContent="WidthAndHeight">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" SharedSizeGroup="MainColumnWidth" />
<ColumnDefinition Width="*" SharedSizeGroup="MainColumnWidth" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" SharedSizeGroup="MainRowHeight" />
<RowDefinition Height="*" SharedSizeGroup="MainRowHeight" />
</Grid.RowDefinitions>
<Border BorderThickness="1" BorderBrush="Black" Grid.Column="0" Grid.Row="0" >
<Button Width="100" Height="100" Margin="10" Content="A" />
</Border>
<Border BorderThickness="1" BorderBrush="Black" Grid.Column="1" Grid.Row="0" >
<Button Width="100" Height="200" Margin="10" Content="B" />
</Border>
<Border BorderThickness="1" BorderBrush="Black" Grid.Column="0" Grid.Row="1" >
<Button Width="200" Height="100" Margin="10" Content="C" />
</Border>
<Border BorderThickness="1" BorderBrush="Black" Grid.Column="1" Grid.Row="1" >
<Button Width="100" Height="100" Margin="10" Content="D" />
</Border>
</Grid>
</Window>
For example, the code above produces the following:
However, I would expect it to produce similar to
Where it sizes to the components but respects the shared group size.
Resizing instantly applies the shared group sizes but then you have to manually guess where the correct size is.
Is there any way to fix this?
If it makes any difference, I am using .NET 5.
Edit
Adding Grid.IsSharedSizeScope="True" to the window or the grid initially appears to solve the issue, but when resizing the window, the grid no longer fills the window.
I suspect that what is happening is that without IsSharedSizeScope, the columns / rows are only the same size due to the Column / Row definition saying width / height is * but when IsSharedSizeScope is true, then the shared size scope come into effect, but for some reason stop the grid resizing when there is space for it to grow.
Looks like you need to use UniformGrid
<UniformGrid Rows="2" Columns="2">
<Border BorderThickness="1" BorderBrush="Black">
<Button Width="100" Height="100" Margin="10" Content="A" />
</Border>
<Border BorderThickness="1" BorderBrush="Black">
<Button Width="100" Height="200" Margin="10" Content="B" />
</Border>
<Border BorderThickness="1" BorderBrush="Black">
<Button Width="200" Height="100" Margin="10" Content="C" />
</Border>
<Border BorderThickness="1" BorderBrush="Black">
<Button Width="100" Height="100" Margin="10" Content="D" />
</Border>
</UniformGrid>
Using a window's SizeToContent="WidthAndHeight" property seems to break a grid's column and row definition's property SharedSizeGroup.
No, in order to take advantage of shared size groups, you have to set a scope for the shared size groups to apply. That is what you do with the IsSharedSizeScope property attached property, which is false by default, which means initially there is no scope defined on any element, so the shared size groups will not apply.
<Grid IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" SharedSizeGroup="MainColumnWidth" />
<ColumnDefinition Width="*" SharedSizeGroup="MainColumnWidth" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" SharedSizeGroup="MainRowHeight" />
<RowDefinition Height="*" SharedSizeGroup="MainRowHeight" />
</Grid.RowDefinitions>
<!-- ...other grid definitions. -->
</Grid>
For example, the code above produces the following: [...] Resizing instantly applies the shared group sizes but then you have to manually guess where the correct size is.
This is not related to shared size groups, but to the Grid itself. You can remove all the shared size definitions and it will yield the same result. In fact, the shared size definitions are redundant, as giving each column and cell a * size, will scale them in the same proportion. See the documentation for reference.
Star sizing is used to distribute available space by weighted proportions.
Unfortunately, I cannot tell why the inital size fits the Grid content exactly instead of respecting the star sizes. However, applying a MinWidth and MinHeight solves the issue, if applicable.
<Grid IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MinWidth="200" />
<ColumnDefinition Width="*" MinWidth="200" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight="200" />
<RowDefinition Height="*" MinHeight="200" />
</Grid.RowDefinitions>
<!-- ...other grid definitions. -->
</Grid>
This could be the same or a similar issue with star-sizing like in this related question.
[...] when IsSharedSizeScope is true, then the shared size scope come into effect, but for some reason stop the grid resizing when there is space for it to grow.
This is expected, since setting a shared size group will treat sizes differently.
Columns and rows that participate in size-sharing do not respect Star sizing. In the size-sharing scenario, Star sizing is treated as Auto.
Consequently, if you apply a *, the Grid will be measured and the size will remain even after resizing.
As you question suggests, you are dealing with uniform cells in your grid. In this case, you can circumvent these issues by simply using the UniformGrid control, which is dedicated for this scenario.
Provides a way to arrange content in a grid where all the cells in the grid have the same size.
<UniformGrid>
<Border BorderBrush="Black" BorderThickness="1">
<Button Width="100" Height="100" Margin="10" Content="A" />
</Border>
<Border BorderBrush="Black" BorderThickness="1">
<Button Width="100" Height="200" Margin="10" Content="B" />
</Border>
<Border BorderBrush="Black" BorderThickness="1">
<Button Width="200" Height="100" Margin="10" Content="C" />
</Border>
<Border BorderBrush="Black" BorderThickness="1">
<Button Width="100" Height="100" Margin="10" Content="D" />
</Border>
</UniformGrid>

TextBox content vertical stretch to available size

My goal is a TextBox that accepts return but only shows 4 lines of text that is alligned to other lines of text, but I'm having some problems that basically seem to boil down to the question: What is the correct way to get the content of a TextBox to vertically stretch to the available space?
A minimal example looks like this:
<Window 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="150" d:DesignWidth="150">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="1" />
<Label Grid.Column="0" Grid.Row="1" Content="2" />
<Label Grid.Column="0" Grid.Row="2" Content="3" />
<Label Grid.Column="0" Grid.Row="3" Content="4" />
<TextBox Grid.Column="1" Grid.Row="0" Grid.RowSpan="4" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch" AcceptsReturn="True" MaxLines="4" Text="1
2
3
4" />
</Grid>
</Window>
But the output is not what I expected:
I tried setting the LineHeigt, but it only "cuts off" the text:
<TextBox Grid.Column="1" Grid.Row="0" Grid.RowSpan="4" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch" AcceptsReturn="True" MaxLines="4" Text="1
2
3
4" TextBlock.LineStackingStrategy="MaxHeight" TextBlock.LineHeight="18" VerticalScrollBarVisibility="Visible" />
edit
Setting a fixed height for the TextBox corrects the behaviour, but that's not really a good way to solve the problem.
The immediate reason for your current issue is because you're using Label instead of TextBlock
The issue this causes is that TextBox renders lines as TextBlock which is a framework element. Whereas Label is a templated control inheriting from ContentControl and has a Padding set by default within it.
So if you you want them to align in your scenario you've got some options such as;
Curb the padding on your Label's;
<Label Padding="0"/>
Or swap them for good old TextBlock (which by the way is a "lighter" control and suggested instead unless using Label is actually necessary).
Or you could adjust your TextBox to reflect the padding of your Label's by targeting TextBlock with attached properties like TextBlock.LineHeight and TextBlock.LineStackingStrategy="BlockLineHeight" which would take some tinkering to get the exact output you want.
Also keep in mind TextBox is also a templated control with an embedded ScrollViewer so there will be a 1px offset for the default BorderThickness
So keeping your original control pairs if we do something like this instead, you'll see the culprit as example;
<Grid ShowGridLines="True"
HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Label Content="1" Padding="0"/>
<Label Grid.Row="1" Content="2" Padding="0"/>
<Label Grid.Row="2" Content="3" Padding="0"/>
<Label Grid.Row="3" Content="4" Padding="0"/>
<TextBox BorderThickness="0"
Grid.Column="1" Grid.RowSpan="4"
VerticalAlignment="Top"
VerticalContentAlignment="Stretch"
AcceptsReturn="True" MaxLines="4"
Text="1
2
3
4" />
</Grid>
Giving the result of;
Hope this helps, cheers.
A textbox could be stretched if it is inside a viebox, like this:
<Viewbox Stretch="Uniform" Grid.Column="1" Grid.Row="0" Grid.RowSpan="4" >
<TextBox Name="textBox" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" Text="1
2
3
4"/>
</Viewbox>
But in similar condition, I'd like to use a DataGrid
Just wrap the Textbox into Grid and set his MaxHeight to Infinity and his Height Value from that Grid:
<Grid x:Name="ValueTextBoxGrid" Grid.Row="1">
<TextBox
MaxHeight="Infinity"
Text="Your Text"
TextWrapping="Wrap"
Height="{Binding ElementName=ValueTextBoxGrid,
Path=ActualHeight}" />
</Grid>

WPF - Canvas Background Not Displaying

I am a complete newbie to WPF. I've been working on a personal project for about 2 weeks. It's been coming along, and suddenly hit a roadblock. Everything was working perfect until I shifted some things around.
It's basically a satellite map as the canvas background, so that I can overlay geometry on it. The image is 10000x10000, and has not changed. It's added as a resource and... funny enough, shows up in the Visual Basic xaml designer.
The local:ZoomBorder class zooms/pans the viewbox/canvas. I did not post the code because it has not been touched since it last worked.
Geometry is being added to the canvas correctly.
I moved around some dimensions, as far as the grid goes. Like adding margins and such, but can't get it back to displaying the imagebrush background, no matter what I do.
<Window x:Class="Temp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Temp"
Title="MainWindow" Height="930" Width="1100" PreviewKeyDown="mapBorder_PreviewKeyDown">
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="210" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ScrollViewer Grid.Row="2" Grid.Column="0">
<StackPanel Name="stackPanel" />
</ScrollViewer>
<local:ZoomBorder x:Name="mapBorder" Background="Gray" Margin="0" Grid.Column="1" Grid.Row="2" ClipToBounds="True">
<Viewbox>
<Canvas Name="mapGrid" Height="10000" Width="10000">
<Canvas.Background>
<ImageBrush ImageSource="map.jpg"/>
</Canvas.Background>
</Canvas>
</Viewbox>
</local:ZoomBorder>
<Button Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" MinWidth="80" Margin="10,0,0,0" Content="Start Refresh" Width="80" Click="buttonStartRefresh" />
<Button Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" MinWidth="80" Margin="110,0,0,0" Content="Stop Refresh" Width="80" Click="buttonStopRefresh" />
<CheckBox Name="Advanced" Grid.Column="1" Grid.Row="1" Margin="10,0,0,0">
<Label Margin="0,-5,0,0">Advanced</Label>
</CheckBox>
</Grid>
</Window>

Childwindow WPF extended toolkit not opening

This is my code to open childwindow:
ImageLocation location = new ImageLocation();
location.WindowStartupLocation = Xceed.Wpf.Toolkit.WindowStartupLocation.Center;
location.Show();
But the childwindow doesn't show at all.
This is my xaml for childwindow:
<xctk:ChildWindow x:Class="CXLocalSearch.Dialogs.ImageLocation"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Caption="Image Path"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Height="64" Width="400">
<Grid x:Name="LayoutRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="63.95"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Margin="2" TextWrapping="Wrap" Text="Image Path" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<StackPanel Grid.Column="1" HorizontalAlignment="Left" Margin="3,2,0,2" Orientation="Horizontal" >
<TextBox x:Name="txtPath" Margin="0,2" TextWrapping="Wrap" VerticalAlignment="Center" Width="250"/>
<Button x:Name="btnSave" Content="Save" Click="btnSave_Click" Width="60" Margin="3,0,0,0"/>
</StackPanel>
</Grid>
</xctk:ChildWindow>
Could anybody please clarify what the issue is?
From the looks of it, you've separated your ChildWindow into a separate control. That's fine, but it needs to be hosted inside a primary window in order to ever become visible. Start with the simplest thing possible:
<Window>
<Grid>
<Button Click="...">Click to Show</Button>
<xctk:ChildWindow x:Name="childWindow">
<TextBlock>Hello!</TextBlock>
</xctk:ChildWindow>
</Grid>
</Window>
I think you'll find this works fine (assumes event hookup), so take it from there.

How to make selectable text with 100% height and 100% width of a Grid Cell

I have a Silverlight application and I try to display a generated text into a Cell of my grid. Unfortunately the TextBox does not seem to be able to have a stretching height and stretching width to his parent size. For the moment, I have simply use a ScrollViewer and Set the content but I can't select the text so I still have a problem.
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="500*" />
<ColumnDefinition Width="20"></ColumnDefinition>
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<Button Content="Generate" Grid.Row="1" HorizontalAlignment="Left" Name="button1" VerticalAlignment="Top" Height="50" Click="GenerateSerialization" />
<ScrollViewer Name="scrollText" Grid.Column="2"></ScrollViewer>
<sdk:GridSplitter Grid.Row="0" Grid.Column="1" HorizontalAlignment="Center" Name="gridSplitter1" VerticalAlignment="Stretch" />
</Grid>
Sorry... when I think I understand English I see have a lot of road to travel :o)
Check this:
<ScrollViewer Name="scrollText"
HorizontalScrollBarVisibility="Disabled"
Grid.Column="2">
<TextBox TextWrapping="Wrap"
Text="Bla, bla, bla..." />
</ScrollViewer>

Categories

Resources