Grid layout issue - wpf

I have the following xaml:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Grid.Column="1">
<TextBox Width="120" Text="Search" Margin="10"/>
<Button>Search</Button>
</StackPanel>
</Grid>
In both the designer and the running application the right edge of the button is cut off, but only if the textbox has a margin on the right side. How do I create separation between the two without cutting off the buttton. Is this a bug?
Edit:
The StackPanel is in Column 1 not Column 0. Additionally, the button border reappears after the button has been clicked. Window size is 525 and the grid is the only thing in it.

Set your first ColumnDefintion's Width to Auto
I'm guessing that since the width is not defined, it's making them both *, which means they'll be of an equal width. By setting the 1st to Auto you're telling it to take up however much space it needs, then letting the 2nd column fill the remaining space.

It isn't a bug- the combination of the 120px of width (of the text box) + the width of the button when it's contents is the string "Search" (whatever that may be) + the 150px of the first column is wider than whatever is the space allocated by the container of the Grid.
What did you expect to happen? Scrollbars?

Related

How can I tell a grid which column to shrink when needed

I'm wanting to limit a Grid.ColumnDefinition to a maximum width but I do not know the width to do this programatically. Consider the following XAML:
<Grid MaxWidth="150" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Text="A" TextWrapping="Wrap" Background="LightGreen" />
<TextBlock Grid.Column="1" Text="B" TextWrapping="NoWrap" Background="LightSteelBlue" />
</Grid>
The Grid is 150px wide at most but can be less. The TextBlock in column 0 is Wrap. The TextBlock in column 1 is NoWrap. Background colors added simply for clarity. Result:
Now let's change the text:
<TextBlock Grid.Column="0" Text="I'm long but I wrap" TextWrapping="Wrap" Background="LightGreen" />
<TextBlock Grid.Column="1" Text="I'm a long single line" TextWrapping="NoWrap" Background="LightSteelBlue" />
Result:
The wrappable text does not wrap. Seems no feedback is provided from the Grid to the TextBlock. The behavior I want is for the Grid to realize that its columns being Auto have expanded past its own MaxWidth property and attempt to shrink the contents in the columns. The TextBlock that is NoWrap won't abide by this request while the TextBlock with Wrap would. Hence the output would be:
I can't figure out a way to do this with any * sizing since I don't want the grid to take this much space unless the contents are needed. Incidentally the actual Grid has many columns of many potential sizes. This is a shortened example.
[Edit]: My solution is a hack and I don't care for it, but it works. I created a property on my model which determines the content that can appear in other columns including images, margins, text, etc. Then it subtracts from the grid size to find a maximum width for a TextBlock which has Wrap set. Works just fine but is ugly as can be.
Although Auto does not work well for you, doing the * can work wonders. Instead of just a blind-eye to * for all other columns, you can do [a numeric value]*, like Width="120*" which will allocate the 120, but, if there is more room, it will get the rest.
Now, that said, if you have SOME columns that you know would be fixed, like some date field which is always 100 width, or some string type category of 1 character, maybe a fixed width of 10, but the rest are otherwise flexible. Just blend them something like
Width 100
Width 10
Width 500*
Width 250*
So, if your screen has available width of 1200, columns 1 and 2 will remain at their fixed widths. However, the 500* and 250* will get their baseline width and then equally split the remaining width between them. The more "*"-based columns to split the widths, they all split the available space.
Have you tried doing something like that?

wpf - Grid column not filling remaining space when other column's contents are collapsed

I've got a grid with 3 columns: the first has its Width set to "*", which I have been led to believe will make it fill up any remaining space left by the other columns. The second has a width of 8, and the third's Width is set to "Auto" so its size changes depending on its contents.
In my 2nd column I have a GridSplitter, so that when dragged I can change the width of both the first and third columns. This works fine, the issue is that I have a grid in my third column that, when toggled, will have its visibility set to collapsed. When collapsed, I need the first column to fill all of the remaining space. I tried to do this many ways:
Set HorizontalAlignment on first column to Stretch
Bound the Grid.Rowspan of the first column to the visibility of the third one, so that when when hidden the Rowspan will change to 3 and, since its width is using "*", it should theoretically use all of the available space in all 3 columns.
The weird thing is that, if I do not resize the columns using the GridSplitter, then the first column will fill all remaining space properly. Yet after resizing, the first column will not budge. It's almost as if, when dragging the GridSplitter to resize the columns, WPF change the width of both columns to become absolute instead of their star and auto values, making it so they will not fill the space after a resize.
XAML Code (condensed) as requested:
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid x:Name="AssetListViewGrid" Grid.Column="0" Grid.RowSpan="{Binding Visibility, ElementName=AssetViewMetadataSplitter, Converter={StaticResource SplitterVisibilityToRowSpanConverter}}" Margin="0 4 0 4">
<!-- irrelevant code -->
</Grid>
<GridSplitter x:Name="AssetViewMetadataSplitter" Grid.Column="1" Opacity="0.8" HorizontalAlignment="Center" Width="6" Margin="3 5 1 5" ToolTip="Grab to resize" Visibility="{Binding IsChecked, ElementName=GridHeaderVisibilityToggleButton, Converter={StaticResource VisConverter}}"/>
<Grid x:Name="MetadataGrid" Margin="4 2 4 2" Grid.Column="2" DataContext="{Binding MetadataViewModel}" Visibility="{Binding IsChecked, ElementName=GridHeaderVisibilityToggleButton, Converter={StaticResource VisConverter}}">
<!-- irrelevant code -->
</Grid>
I just ran into this as well. In my app it seemed that a GridSplitter was in fact changing the width values to absolute instead of * also, so I'm guessing that is the behavior.
I ended up using code-behind to solve it. First, name column 1:
<ColumnDefinition Width="*" x:Name="Column1"/>
Then, add an event handler for when your MetadataGrid visibility changes, & call this code to reset Column1 to a * width to fill the rest:
Column1.Width = new GridLength(1, GridUnitType.Star);
You might also try doing something in the XAML with style triggers to reset the Column1 width to * based on the MetadataGrid's visibility state. My case was much more complex with custom sizes & varied conditions & expanders, so I used code-behind, so I'm not sure if xaml triggers would work for yoU or not . Hopefully that helps though.
I solved it by adding empty 10000X1000 rectangle inside it
<Grid Grid.Row="1" Grid.Column="1" Height="auto" HorizontalAlignment="Left" SizeChanged="Grid_SizeChanged">
<Image x:Name="currentImage" Height="auto" Width="auto" />
<Rectangle Width="10000" Height="10000" ></Rectangle>
<Canvas x:Name="currentImageOverLay"/>`</Grid>

How to align buttons on opposite sides of window in WPF?

trying first time WPF user. I read through some WPF layout docs but am not getting the hang of the layout of buttons. I'm trying to get the layout below -- where there's a button in the lower left corner and two in the lower right.
Can this be done with a single StackPanel? I tried unsuccessfully with this along with the HorizontalAlignment attributes of the buttons.
Is it more appropriate to be using a 1 row, 2 column grid, with each cell having a StackPanel?
Any suggestions much appreciated, thanks!
Personally, I tend to prefer doing this with a Grid, ie:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Width="100">b1</Button>
<Button Grid.Column="1" Width="100">b2</Button>
<Button Grid.Column="2" Width="100">b3</Button>
</Grid>
This will cause the 2nd & 3rd columns to fit their contents, and the first to fill the rest of the space. If you place each button in the appropriate column, you'll get that layout. (Note that you'll likely want to adjust the sizing and margins on the buttons to get nice spacing, as well.)

Letting a child control width size to fit and limiting its max value

Edit: I try rephrasing my question, sorry if it was not clear. Thanks to all anyway.
Say I have a UserControl whose layout has a grid with 1 row x 3 columns, the first 2 autosized and the third star-sized:
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ComboBox MinWidth="80" MaxWidth="150" .../>
<CheckBox Grid.Column="1" VerticalAlignment="Top".../>
<TextBox Grid.Column="2" MaxHeight="400" TextWrapping="Wrap" HorizontalAlignment="Stretch"...>
</Grid>
The TextBox has text wrapping and its vertical scrollbar visibility set to auto and its horizontal one hidden.
Now, I have some window including a ListBox whose items are instances of this UserControl, like:
<ListBox HorizontalContentAlignment="Stretch".../>
The ListBox is in a 1-column star-sized grid and thus stretches to fit all the available width in its container. When I resize the container of this ListBox the ListBox too resizes as expected as it is stretched in a star-sized Grid column; and the same holds true for the ListBox items', which too are stretched and in this case happen to be instances of a UserControl with the above layout (3 columns in a grid, the 3rd star-sized).
The problem is that the TextBox in the 3rd column of the UserControl used as a listbox item should not automatically increase its width when I type into it some long text: it should just wrap, increasing its height (up to a maximum height; then the vertical scrollbar will appear). In other words, its MaxWidth should be determined by the available space, like its Width.
How should I code my XAML for this?
That should be the behavior by default, based on the code you've posted.
Try setting your TextBox's HorizontalAlignment="Stretch"

WPF TextBox autogrow

I have a TextBox with a height=15 and width=50. I want the textbox to grow when the text size exceeds 50. I want to achieve this without using Width="Auto". Is there any way to achieve this? I tried TextWrapping = TextWrapping.Wrap without any success.
Appreciate your help!!
Set the MinWidth=50
Let's say your text box is inside a grid which has 2 columns
<Grid>
<Grid.ColumnDefinitions>
//The first column is used for a label
<ColumnDefinition Width="Auto"/>
//This column is used for your text box
<ColumnDefinition Width="*"
MinWidth="25"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
Content="Something:"
/>
<TextBox Grid.Column="1"
Content="BindToProperty"
/>
</Grid>
and the height and width of your user control is set to
Auto
So whenever you place the user control on to other controls, it will have the minimum width of
25 + label width
. If you want to increase the width, you can set the width directly to your user control, and the Textbox will be stretched out.
Cheers

Resources