Silverlight Grid inside of TabItem header - silverlight

My custom TabItem header looks like this:
<sdk:TabControl>
<sdk:TabItem >
<sdk:TabItem.Header>
<Grid Background="Gray" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<!-- some labels go here -->
</Grid>
</sdk:TabItem.Header>
</sdk:TabItem>
</sdk:TabControl>
This creates a single-row, two-column grid inside of the TabItem header. The grid automatically sizes to fit the labels, like it should, but when the size of the actual tab button grows, the grid does not adjust to fill the space (even though I specifiy <HorizontalAlignment="Stretch">).
Why is this? Is there a way to have the grid take up all available horizontal space in the header?

The problem is that the default template for a TabItem which is used to render the tab places the content of the header in a ContentControl. Now a ContentControl has the properties HorizontalContentAlignment and VerticalContentAlignment that have the default values of "Left" and "Top". This is why your grid only occupies the space it needs rather than stretching to the full size available.
In order to avoid this you will need to make a copy of the default template for the TabItem and assign the value "Stretch" to both of those properties on the ContentControl elements in the template (there are 8 in all, 2 for each possible TabStrip placement (Top, Left, Bottom and Right) ).

Related

Difference between GridView and Grid

Can anyone tell me the difference between GridView and a Grid in WPF XAML?
Here are the details for UWP. Should be similar for WPF I think.
Grid - used for defining layouts and formatting or static information. It is one of the several "layout panels" that are available (others include: RelativePanel, StackPanel, VariableSizedWrapGrid, and Canvas). Grid does not have an ItemSource member to dynamically display items by binding. Grid does have Grid.Row and Grid.Column attached properties (i.e. that can be used on other controls) to position them within the Grid.
Sample Code:
<Grid x:Name="LayoutPanel1" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
Margin="20"
BorderBrush="{StaticResource Page_Brush}"
BorderThickness="1 1 1 1">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="44"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
More Information: Grid Class, Layout Panels
GridView - used for displaying a set or collection of data (i.e. dynamic number of items). Another control available to display a set or collection of data is a ListView. One way to use this is by setting ItemSource (i.e. binding). By default, a data item is displayed in the GridView as the string representation of the data object it's bound to. To specify exactly how items in the GridView are displayed, you create a DataTemplate to define the layout of controls used to display an individual item. The controls in the layout can be bound to properties of a data object, or have content defined inline. You assign the DataTemplate to the ItemTemplate property of the GridView. The DataTemplate can contain a Grid (or any of the other layout panels mentioned above) to specify the layout of controls of an individual item.
Sample Code:
<GridView ItemsSource="{x:Bind MyItems}"
IsItemClickEnabled="True"
ItemClick="GridView_ItemClick"
ItemTemplate="{StaticResource MyItemTemplate}"
BorderBrush="{StaticResource MyItemBrush}"
BorderThickness="1 1 1 1"
HorizontalAlignment="Stretch"
/>
More Information: GridView Class, List view and Grid view, Guidelines for list view and grid view
A simple explanation would be
Grid
If you have just a single item with no repetitive subitem design then a grid is used. If the number of subitems are fixed
GridView
If you have a repetitive design like collection and you dont know the number of items that can be present then a gridview is used instead.
You can find more details on msdn forums.
From what I see Grid is more like a table, each row contains the same number of items (one for each column) no matter the size of the window.
GridView looks like a table but if you reduce the width of the window, the items from one row will jump on the next row:

Autosize canvas in wpf

How can canvas in wpf be autosized? I have a canvas in scrollviewer and I will add several buttons and lines in this canvas in code behind. since I don't know the position of the buttons, I have to hard code a very large number for the width and height of the canvas or if I add too many buttons, it can only show part of them.
I try to set the Width and Height to Auto but it doesn't work.
<Grid>
<ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible">
<Canvas Width="Auto" Height="Auto" Name="cv1"></Canvas>
</ScrollViewer>
</Grid>
The Canvas element is the only element that can not be automatically resized, because has no inherent layout characteristics. If you want the Control to be resized as child elements come in, you could use something deriving from Grid.
Try a UniformGrid instead of your Canvas ans fill it with the elements you want. It allows you to just add elements without any layout constraints that are handled by the UniformGrid. otherwise if you use a simple Grid, you will have to define a Position for your element by setting the Margin property of each child element.
Hope this helps.

TabControl Width Height issue

I'm using a TabControl with no Height and Width specified.
Actually, the height of the TabControl take the height of the current tab.
I don't want the TabControl auto adjust it size. I want it take the size (Heigth and Width) of the biggest tab.
How can I do that ?
Thanks.
Because some people asked for the actual xaml, here is something that worked for me. It is based on the tips from #FWillem, #Floc and the others, so all credit goes to them.
<TabControl>
<TabItem Header="SomeTab1">
<Grid Name="MasterTabGrid">
<!-- Some content -->
</Grid>
</TabItem>
<TabItem Header="SomeTab2">
<Grid Height="{Binding ElementName=MasterTabGrid, Path=ActualHeight}" >
<!-- Some other content -->
</Grid>
</TabItem>
</TabControl>
The size of your TabControl will be being set by its parent container control, which is responsible for the layout of its children, and will specify default values for many layout properties.
If, for example, you place the TabControl inside a (vertical) StackPanel, you'll find that it takes the minimum vertical space that it can. If you have a Grid around your tabs, they'll fill the available space.
Alternatively, you can manually set VerticalAlignment="Top" with other containers, and this will typically override the behaviour you're seeing. (Most likely your layout panel is defaulting this to Stretch.)

How to Hittest Grid ColumnDefinition?

I am making kind of WPF Designer. I want to find out ColumnDefinition i have clicked on to delete it from grid control. I will take care of those children who "are in that ColumnDefinition".
Can i get it from sender argument of click event handler?
Now im checking if e.GetPosition is in range of ColumnDefinition.ActualWidth but i wonder if there is more beautiful solution.
From within your click event handler:
int columnIndex = Grid.GetColumn((UIElement)sender);
where sender if a direct grid's child.
Why do you need to capture a click on ColumnDefinition anyway? Is virtual, it does not have any actual body, it is only a hint for Grid on how you want to layout its content.
So you have to set handlers on content objects, not on ColumnDefinition.
If you really need to capture a click on the whole surface of a grid cell, you may try to place a white (or other color the same as background) Reactangle inside it and capture a click on it.
Some clarification on how WPF Grid works.
When you add some controls to the Grid, they all become its children.
<Grid>
<Button/>
<TextBox/>
<Label/>
</Grid>
And they all will be displayed not regarding how you have configured Column or RowDefinitions.
Column and RowDefinitions only tell Grid how you want to aling all the existing elements inside it, but they are not containers, they don't hold elements inside.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button/><!-- this is identical to Grid.Column="0"-->
<TextBox Grid.Column="1"/>
<Label Grid.Column="2"/>
</Grid>
In this example we have created three ColumnDefinitions, even from the grid XAML you can see, that controls are not inside definitions. They are used just like ruler guides to align content.
Then you set attached properties on the elements to tell the grid where you want to put your elements.
When grid begins layout, it will see, that there are three elements, and three ColumnDefinitions, and will try to positions elements as ColumnDefinitions says.
But if you remove or change ColumnDefinitions in the runtime, grid will just realign controls in a new way.
If you want to hide some elements, you have to hide them, not ColumnDefinition.

DataGrid not shirking to fit into the containing grid

I have the following structure in my WPF application. (Using Prism and Regions)
Window---->
UserControl---->
DockPanel------>
Grid(2X2)------>Row0Col0--
Grid (2X1)------>
ItemsControl------>
UserControl(injected into ItemsControl with Prism)----->
DockPanel----->
DataGrid.(60 rows, 10 columns)
The behavior that I expect is that the DataGrid will size itself to fit the size of the grid cell and display both scrollbars because it is too big to fit. But it doesnt. It remains its maximum size and cuts out of the edges of the grid cell. All cells of both grids have no size specifications (Auto Sized). When I explicitly specify datagrid's height and width, I see the scrollbars, but of course I don't want to do that.
Please help!.
Thanks
I have saved the screenshots at the following link.
http://s1199.photobucket.com/albums/aa467/vikasgoyalgzs/
You say: "All cells of both grids have no size specifications (Auto Sized)" - this is where the problem is. When the grid cell is auto sized the grid gives the content in that cell as much space as it wants (doesn't matter if it fits in the window or not). To fix it you have to put your DataGrid into a star-sized cell.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0">
<!-- Content that will take as much space as it wants -->
</Border>
<Border Grid.Row="1">
<!-- Content that will take all the remaining space -->
</Border>
</Grid>
UPDATE: Based on the screenshots you provided...
First, get rid of the DockPanel in the top level control. DockPanel gives its child all the space it asks for. If it is not a "fill" child (LastChildFill="True"). Use grid instead of DockPanel (i.e. at the top level a grid with two rows - one auto-sized for the menu and the second star-size for the rest of the stuff, the in that star-size row put another grid for you items controls, etc.).
Remember, whenever you put the content either in an auto-size cell in a grid or in a DockPanel with dock type different than Fill, the content will take as much space as it required without showing a scroll bar (it will go beyond the window).
UPDATE 2: Looking at the new screenshots (see comments to this post)...
OK, I think I see the problem. The thing is that ItemsControl uses StackPanel to display its children, but StackPanel also gives its children all the space they want (your DataGrid thinks that it has enough space to render itself without scroll bars).
To fix that you need to put your items controls inside an ScrollViewer like this:
<ScrollViewer VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto">
<ItemsControl ... />
</ScrollViewer>

Resources