UserControl cropped when used in MainWindow - wpf

Hello Stackoverflowers !
I'm creating a list with a searchbar in XAML, and when i tried to use my new UserControl in MainWindow.xaml, the Button in the UserControl is cropped in the designer instead of being resized to fit, why is that ?
Here is the MainWindow.xaml body :
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="8*" />
</Grid.ColumnDefinitions>
<controls:SearchBox Grid.Column="0"/>
</Grid>
And here is the body of the custom control :
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="8*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="8*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBox
Grid.Row="0"
VerticalAlignment="Center"
Text="Search"
TextBlock.FontStyle="Italic"
TextBlock.TextAlignment="Left"
/>
<!-- Content="{StaticResource FilterLogo}" -->
<Button
Grid.Column="1"
Content="Filter"
VerticalAlignment="Center"
HorizontalAlignment="Stretch">
</Button>
<ListBox
Grid.Row="1"
Grid.ColumnSpan="2"
ItemsSource="{Binding DataContext}"
SelectedItem="{Binding DataContext}"
ScrollViewer.VerticalScrollBarVisibility="Visible">
</ListBox>
I don't really know why my control is cropped to be honest. Any lead please ?

Short answer: it doesn't fit.
You have two columns in your main window. Since you have not specified which column to place the UserControl, it defaults to the first column. But your Width definitions force that column to be one fourth the size of the second column.
Your SearchBox simply doesn't fit in the space you have allotted to it.
If you remove the star (*) from this line:
<ColumnDefinition Width="8*" />
...it will fit without being cropped. (Alternatively, you could place the user control in the second column, or expand the main window, or shrink the width of your UserControl.)

When using stars in the column and row definitions, use them like percentages. Like this:
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".1*" /> <!-- 10% -->
<ColumnDefinition Width=".9*" /> <!-- 90% -->
</Grid.ColumnDefinitions>
This is what the XAML reader interpreted from your usage:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="8*" /> <!-- 800% -->
<ColumnDefinition Width="*" /> <!-- 100% -->
</Grid.ColumnDefinitions>
This will have undesired results.

Related

Can't get column sizes to match in two Grids, one inside a TabControl

I am working on a dialog box in my WPF application. The dialog contains a number of nested Grid controls and a TabControl, as shown below.
<Window . . .>
<Grid Name="LayoutRoot>
<Grid.RowDefinitions>
<RowDefintion Height="*" />
<RowDefintion Height="Auto" />
</Grid.RowDefinitions>
<Grid Name="Common" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Column1" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" SharedSizeGroup="Column2" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefintions>
<RowDefintion Height="Auto" />
<RowDefintion Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" . . . />
<TextBox Grid.Column="1" Grid.Row="0" . . . />
<TextBlock Grid.Column="2" Grid.Row="0" . . . />
<ComboBox Grid.Column="3" Grid.Row="0". . . />
<TabControl Grid.Column="0" Grid.ColumnSpan="4" Grid.Row="1" Name="Tab1">
<TabItem Header="Tab 1">
<Grid Name="Tab1Grid" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Column1" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" SharedSizeGroup="Column2" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefintions>
. . .
</Grid.RowDefinitions>
. . .
</Grid>
</TabItem>
<TabItem Header="Tab 2">
. . .
</TabItem>
</TabControl>
</Grid>
<!-- Other controls here in the second row of the outer most Grid -->
</Grid>
</Window>
The point of all of this is to keep the width of the columns that contain TextBlock controls the same, however, it's not working that way. The Width="Auto" attributes seem to be overriding the SharedSizeGroup attributes. If I remove the Width attributes from both Grids, they're as big as the biggest string in both columns, but that's not what I want, either. I want the width of the first column in the Grid inside the TabControl's first TabItem to be wide enough to hold the longest string in that column, and then I want the first column in the Grid that holds the TabControl to be the same size. Similarly for the third column.
I hope this makes sense.
Can this be done, or am I misunderstanding how the SharedSizeGroup feature works?
You are not misunderstanding the SharedSizeGroup feature. However, to make it work, you must also define a scope so that WPF knows where to look for the shared size groups. To do this, you use the Grid.IsSharedSizeScope property on a container that contains all of the grids that you use the shared size group for. In your example, it would be this one:
<Grid Name="LayoutRoot" Grid.IsSharedSizeScope="True">
Note that this attached property can be set on any control type, it does not necessarily have to be a Grid.
In your case, you have to be careful, because the TabControl pushes its whole content to the right, so your columns will not exactly align. You'll have to play around with some margins to make it work (the SharedSizeGroup will only make the size the same, not the position).
Hope this helps, FYI your code snippet is full of typos, I would suggest running it through Visual Studio first next time...
Looking at your code, it looks as though you want column 0 in the parent grid to be the same width as column 0 in tab 1. Similarly column 2 in the parent to be the same as column 2 in Tab 1.
If this is the case then give column 0 and column 2 in the parent grid names then bind the width of column 0 and column 2 in tab 1 to ActualWidth property of the appropriate elementName.
i.e.
<Window . . .>
<Grid Name="LayoutRoot>
<Grid.RowDefinitions>
<RowDefintion Height="*" />
<RowDefintion Height="Auto" />
</Grid.RowDefinitions>
<Grid Name="Common" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" Name="ParentCol0" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" Name="ParentCol2" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefintions>
<RowDefintion Height="Auto" />
<RowDefintion Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" . . . />
<TextBox Grid.Column="1" Grid.Row="0" . . . />
<TextBlock Grid.Column="2" Grid.Row="0" . . . />
<ComboBox Grid.Column="3" Grid.Row="0". . . />
<TabControl Grid.Column="0" Grid.ColumnSpan="4" Grid.Row="1" Name="Tab1">
<TabItem Header="Tab 1">
<Grid Name="Common" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width={Binding ActualWidth, ElementName="ParentCol0" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width={Binding ActualWidth, ElementName="ParentCol2" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefintions>
. . .
</Grid.RowDefinitions>
. . .
</Grid>
</TabItem>
<TabItem Header="Tab 2">
. . .
</TabItem>
</TabControl>
</Grid>
<!-- Other controls here in the second row of the outer most Grid -->
</Grid>
</Window>

Give equal width to controls inside a Stack Panel

I need to have two RadCharts inside a horizontal StackPanel and want both the charts to be of equal width. I don't want to give explicit length to the width of the charts. This can be easily achieved by using a Grid control but my scenario requires a StackPanel.
Often the documentation is not quickly comprehensible because it is either written in a confusing way or the needed information is hidden among a ton of other information that doesn't help in the particular case. And so, in my opinion, even if it is a "basic thing", it doesn't hurt to give a quick answer (or if one thinks it is too primitive, he/she should just post nothing at all).
<StackPanel Orientation="Horizontal" Grid.IsSharedSizeScope="True">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="MySizeGroup" />
</Grid.ColumnDefinitions>
<Button Height="23" Content="Reset" Padding="5,1" />
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="MySizeGroup" />
</Grid.ColumnDefinitions>
<Button Height="23" Content="Set" Padding="5,1" />
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="MySizeGroup" />
</Grid.ColumnDefinitions>
<Button Height="23" Content="Import" Padding="5,1" />
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="MySizeGroup" />
</Grid.ColumnDefinitions>
<Button Height="23" Content="Export" Padding="5,1" />
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="MySizeGroup" />
</Grid.ColumnDefinitions>
<Button Height="23" Content="Create new" Padding="5,1" />
</Grid>
</StackPanel>
Hope this helps :)
Put them into individual Grids, use a column with a common SharedSizeGroup and set Grid.IsSharedSizeScope to true on the StackPanel.

Help with my WPF Layout

I have a WPF Line of business application. Most of it is hosted in user controls in tabs.
I'm having an issue finding out how to layout this so it would fit any resolution (with scrolling if necessary).
Here's the issue described in code because i really can't figure out how to put this to text, if it's not clear please let me know i'll try to draw something up.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition> <!--What i actually want to say here isn't "take all remaining space" but "take all remaining space without scrolling,
and then scroll based on everything as if this was auto and no longer *-->
<ColumnDefinition Width="Auto"></ColumnDefinition><!--But what happens for now is that since this is auto , it will not scroll at all untill the * column has fully scrolled-->
</Grid.ColumnDefinitions>
<StackPanel>
<StackPanel Orientation="Horizontal">
<Label></Label>
<TextBox></TextBox>
</StackPanel>
</StackPanel>
<StackPanel Grid.Column="1">
<StackPanel Orientation="Horizontal">
<button> <!-- I want the button's container to be in an auto column , don't
want it to take size away from the fields unless needed but don't
want it to stay visible at the expense of the fields either -->
</StackPanel>
</StackPanel>
<TelerikGrid:RadGridView Grid.Row="1" Grid.ColumnSpan="2">
<TelerikGrid:RadGridView.Columns>
<TelerikGrid:GridViewDataColumn Width="*"/> <!-- This makes my grid take a bajillon kilometers because it itself is in a Grid's column of * size itself in a scrollviewer -->
</TelerikGrid:RadGridView.Columns>
</TelerikGrid:RadGridView>
</Grid>
Hard to tell given I cannot load your GridView control in a Window.
I recommend nesting a layout manager Grid for your controls inside your Grid to create a separation between your controls and the GridView. You also should consider combining all the controls in one StackPanel or other layout manager.
Regardless, this layout gives you separation between the controls and the GridView regardless of your choice of layout manager with no need to specify a column span.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!-- Place a layout Grid inside your Grid to deal with controls -->
<Grid Grid.Column="0" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- Removed your nested stack panel -->
<StackPanel Grid.Column="0" Grid.Row="0" Orientation="Horizontal">
<Label></Label>
<TextBox></TextBox>
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="0" Orientation="Horizontal">
<Button />
</StackPanel>
</Grid>
<!-- Add a spilter bar here -->
<!-- No need to span 2 columns anymore... -->
<TelerikGrid:RadGridView Grid.Column="0" Grid.Row="1" >
<TelerikGrid:RadGridView.Columns>
<TelerikGrid:GridViewDataColumn Width="*"/>
</TelerikGrid:RadGridView.Columns>
</TelerikGrid:RadGridView>
<!-- Add a status bar here -->
</Grid>

XAML for Three way splitter in WPF

I want to split the main window in three way Grid Spliiter same alike outlook style.
and all the controls nested inside in the three window is resized using Grid Splitter.
I am trying to do that using defining Row Definition of Grid and placing each control in Row 1 or column 1..
Its nice to have , if any body has some kind of template to kick start with this kind of layout.. I don't want too complex sample..
This is a perfect resource - Build an Outlook 2007 UI Clone
You can download the full demo(OutlookUI HOL Basic - Final), I think it is what you are looking for
Edit(after comment)
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="1" Width="1" />
<GridSplitter Grid.Column="3" Width="1" />
</Grid>

What does the WPF star do (Width="100*")

What does exactly the star in size terms in WPF mean?
In a WPF Grid, Width="*" or Height="*" means proportional sizing.
For example: to give 30% to column 1 and 70% to column 2 -
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="7*" />
And likewise for rows -
<RowDefinition Height="3*" />
<RowDefinition Height="7*" />
The numbers do not have to be integers.
If the Width for RowDefinition (Height for ColumnDefinition) is omitted, 1* is implied.
In this example, column 1 is 1.5 times wider than column 2 -
<ColumnDefinition Width="1.5*" />
<ColumnDefinition />
You can mix auto-fit and fixed widths with * (proportional) widths; in that case the * columns are apportioned to the remainder after the auto-fit and fixed widths have been calculated -
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <!-- Auto-fit to content, 'Hi' -->
<ColumnDefinition Width="50.5" /> <!-- Fixed width: 50.5 device units) -->
<ColumnDefinition Width="69*" /> <!-- Take 69% of remainder -->
<ColumnDefinition Width="31*"/> <!-- Take 31% of remainder -->
</Grid.ColumnDefinitions>
<TextBlock Text="Hi" Grid.Column="0" />
If you have 2 columns like this:
<ColumnDefinition Width="10*"/>
<ColumnDefinition Width="*"/>
it means that the first column is 10x wider than the second. It's like saying "10 parts column 1, and 1 part column 2."
The cool thing about this is that your columns will resize proportionally. Other options are:
//Take up as much space as the contents of the column need
<ColumnDefinition Width="Auto"/>
//Fixed width: 100 pixels
<ColumnDefinition Width="100"/>
Hope that helps!
we take following example.....
A grid has 3 columns each containing one button of width 100.
XAML Code is...
<Grid x:Name="LayoutRoot" Width="600">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="button1" VerticalAlignment="Top" Width="100" />
<Button Content="Button1" Height="23" HorizontalAlignment="Left" Margin="0,10,0,0" Name="button2" VerticalAlignment="Top" Width="100" Grid.Column="1" />
<Button Content="Button2" Height="23" HorizontalAlignment="Left" Margin="0,10,0,0" Name="button3" VerticalAlignment="Top" Width="100" Grid.Column="2" />
</Grid>
But actually its size is....
<Grid.ColumnDefinitions>
<ColumnDefinition Width="375" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="125" />
</Grid.ColumnDefinitions>
Conclusions:
Total size of grid is 600
Auto : Column is resizes based on it's contents. (2nd column has button of width 100)
* : 1st column width is 3x of 3rd column.
In addition, you can leave out the "*" if that's the element of unit size. So using Pwninstein's code example, it would just be:
<ColumnDefinition Width="10*/>
<ColumnDefinition/>

Resources