I'm a relative WPF newbie and am still trying to get my head around its basics. I have just came across a grid sizing issue which has me stumped (and it seems that is not limited to just grids alone).
The problem is that if I have a grid with relatively sized rows/columns, within a row/column of another grid, with that row/column dimensions being set to auto, the relative sizing for the child grid seems to have no effect.
What I would expect for this xaml, is that the inner grid columns are still relatively sized (with one being 3x the width of the other) even if they are inside an auto-sized column of parent grid. Is this expected behaviour, is this a bug or am I missing something basic?
Thanks!!
Try this:
<Grid Background="DarkBlue">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label BorderBrush="White"
BorderThickness="1"
Content="Cell 1"
Foreground="White" />
<Grid Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Label BorderBrush="White"
BorderThickness="1"
Content="Cell 2"
Foreground="White" />
<Label Grid.Column="1"
BorderBrush="White"
BorderThickness="1"
Content="Cell 3"
Foreground="White" />
</Grid>
</Grid>
The reason that second grid was behaving strangely is because the column of the first grid is set to Auto.
As it's auto it's trying to squash everything inside it to be as small as possible - without the labels this would be a width of 0 for each column of the second grid. Plus the width of the labels makes them about equal.
I believe it has something to do with the order in which WPF calculates widths of something in an auto column/row.
The first thing it does is notice the auto value of the second grid, which is 0. THEN, after that it adds whatever the width of the contents are to this calculated value - as both labels are about the same size, this results in two similar columns.
My solution removes the auto value and instead says the the first column of the first grid "of the total width, you get 2/3rds of the space, and the other column gets 1/3rd" - it's not auto, so the second column is not being squashed in any way.
it seems outer Grid column dictate which width inner Grid should have. Try reverse measure order by binding column width to inner grid width: <ColumnDefinition Width="{Binding Path=ActualWidth, ElementName=InnerGrid}"/>
<Grid Background="DarkBlue">
<Grid.Resources>
<Style TargetType="Label">
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderBrush" Value="White"/>
<Setter Property="BorderThickness" Value="1"/>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="{Binding Path=ActualWidth, ElementName=InnerGrid}"/>
</Grid.ColumnDefinitions>
<Label Content="Cell 1" />
<Grid Grid.Column="1" Name="InnerGrid" Background="DarkRed">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Label Content="Cell 2.1" />
<Label Grid.Column="1" Content="Cell 2.2" />
</Grid>
</Grid>
after resize only 1st column is increasing (see screenshot)
Related
I have a problem designing my GUI in wpf.
How do i set the Grid ColumnDefinition Width dynamically,
I have a expander. And when the expander is clicked the grid should also expand and adjust with the size of the expander
As of now i have this GUI
enter image description here
And this is the xaml code
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="127"/>
<ColumnDefinition Width="665*"/>
</Grid.ColumnDefinitions>
<Expander Background="Gray" x:Name="expander" ExpandDirection="Right" Expanded="Expander_Expanded" >
<Expander.Header>
<TextBlock Text="Objects">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"/>
</TextBlock.LayoutTransform>
</TextBlock>
</Expander.Header>
<StackPanel Margin="10,4,0,0">
<CheckBox Margin="4" Content="Option 1" />
<CheckBox Margin="4" Content="Option 2" />
<CheckBox Margin="4" Content="Option 3" />
</StackPanel>
<!-- Stuff XD -->
</Expander>
<Grid Grid.Column="1" Background="Red"/>
</Grid>
As of now the ColomnDefinition width is 127
I want it to adjust to at least 30. So the window will be filled with other stuff
like this
enter image description here
But my problem is how do i expand the grid when the expander is expanded.
And another thing. I can't get the size of the expander when expanded. It gives me NaN which i can't use to set the columndefinition width
Thank you so much. Sorry for my bad english
Use Auto in first column Width and it will define size of expander based on content.
If you would like that column "0" has some min Width just set the property MinWidth. (but in that case I will not recommend, but show below)
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="30"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
Also I will recommend use GridSplitter, then you will have splitter between two columns that allows to change width of columns by user in UI
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="30"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="DarkSalmon"/>
Also in expander you can only have one user-control, so "stuff" you said need to be inside some layout control like stack-panel,dock or another grid etc.
Let me know if it works as you expected.
I have a grid with a Datagrid attached. I am having issues created a datagrid that resizes as the window resizes. I have set MinHeight and MinWidth, but it just seems to create a static Height and Width. I also have scroll bar set to be visible, but no scroll bar appears?
The closest I've come to responsive design is setting my Height="2300" and Width="2700", but the scroll bar still doesn't appear. And the table I plan to populate my Datagrid with will likely be much bigger than these dimensions, and need scrolling.
I have tried using techniques from other SE questions, but nothing seems to work how I'd expect.
<!--Grid View Assett Info - Populate Table from DB -->
<Grid x:Name="grid_AssetView" VerticalAlignment="Top" Margin="10,236,10,10" Style="{StaticResource Grid_Shadow}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DataGrid VerticalAlignment="Top"
Margin="0,0,0,0"
Grid.Column="0" Grid.Row="0"
ScrollViewer.CanContentScroll ="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
MinWidth="772" MinHeight="230"/>
</Grid>
My Style Sheets
<Style x:Key="Grid_Shadow" TargetType="Grid">
<Setter Property="Background" Value="#FFF9FBFD"/>
<Setter Property="BitmapEffect">
<Setter.Value>
<DropShadowBitmapEffect
Color="Black"
Direction="320"
ShadowDepth="10"
Softness="50"
Opacity="0.1">
</DropShadowBitmapEffect>
</Setter.Value>
</Setter>
</Style>
u have to set the ColumnDefinition Width="*" instead of "Auto" as follows
<!--Grid View Assett Info - Populate Table from DB -->
<Grid x:Name="grid_AssetView" VerticalAlignment="Top" Margin="10,236,10,10" Style="{StaticResource Grid_Shadow}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DataGrid VerticalAlignment="Top"
Margin="0,0,0,0"
Grid.Column="0" Grid.Row="0"
ScrollViewer.CanContentScroll ="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
MinHeight="230"/>
</Grid>
then the datagrid will resize automatically. I also removed MinWidth to show that resizing works without problems.
Also the scrollbars will be visible if there are contents.
I hope it helps.
I have two borders in a winwdow, the first one contains a listbox which has size set through margins. So I can change the window size--->the border changes---> the listbox changes. I'd like to know what it's width is but the width property reports Nan while the actualWidth report 0.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border x:Name="Border1" BorderBrush="Gainsboro" BorderThickness="5" CornerRadius="8,8,3,3" Margin="10,10,168.8,10.4" >
<ListBox x:Name="lbButtons" Background="{x:Null}" BorderBrush="{x:Null}" Height="338" Margin="0,0,0.4,0"/>
</Border>
<Border x:Name="Border2" BorderBrush="Gainsboro" BorderThickness="5" CornerRadius="8,8,3,3" Grid.ColumnSpan="2" Margin="263,10,9.2,10" />
</Grid>
This is something valid for each control: how to know its present size when it's not specified?
thanx
It is possible that the component is not yet displayed at the point where you get its size. You can get the right actualWidth in the loaded event of the object.
I have been trying to get dynamic column width to work for my simple WP8.1 app. The goal is to have the first column take up half of the listbox, and the other two columns a quarter each. I hoped to do this by assigning a dynamic width, using the * indicator as described here.
This let me to the piece of xaml code at the bottom of my post.
In my MainPage I set the DataContext to an ObservableCollection, and all the data shows up in their respective columns, the columns just do not get the desired width (they are all as small as can be).
What prevents my dynamic width from working? I have toyed around with HorizontalAlignment and Width of TextBoxes too, but with no success. I tried to look around for answers, and I even used some examples that did work, but that did not bring me closer to understanding why it does not work here.
Thanks in advance.
<Grid>
<ListBox Name="transactionListBox" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding Name}"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Category}"/>
<TextBlock Grid.Row="0" Grid.Column="2" Text="{Binding Amount}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
The item Grid itself is being sized-to-fit by the ListBox. You can override this behavior by setting the ItemContainerStyle to make the ListBoxItems stretch to fill horizontally:
<ListBox Name="transactionListBox" ItemsSource="{Binding}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>
...
</ListBox>
I think you need a constraining width on the ListBox or Grid. With your code, the grid and ListBox will re-size to fit the content, so there is no need for the dynamic column definitions.
Inside my XAML/C# app for Windows 8 Store, I am trying to create a ListView where each ListItem is a horizontal Grid, so I am using the XAML below:
<ListView Name="ResultsView">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="4*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding BestRank}" Grid.Column="0"/>
<TextBlock Text="{Binding PlayerName}" Grid.Column="1"/>
<TextBlock Text="{Binding BestScore}" Grid.Column="2"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
When I run this program, the listview contains all the items from the list it is bound to (through code behind). However in every list-item, contents of all three columns appear together without any space between them. When I create a similar grid outside the listview, it displays fine and takes up entire width of the screen and divides it between the three columns as specified in the XAML above.
What am I doing wrong?
I believe the issue is the ItemContainerStyle needs to have a HorizontalContentAlignment of Stretch. Try this adding this to the ListView:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
Both the ListBox and the Grid should have HorizontalContentAlignment="Stretch"
Specify the width of the grid or add the style as a resource to the grid. Add this right after your </Grid.ColumnDefinitions> line.
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="TextAlignment" Value="Right" />
<Setter Property="Margin" Value="4" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</Grid.Resources>
This will set the properties to all of the TextBlocks in the Grid. You might only need the Margin property. Also consider the properties Width and Padding. You can override this default by setting the property on any given TextBlock to something that isn't the default from the Style.
The default ItemsPanelTemplate is a stack panel as far as I recall meaning that it won't automatically give it's children stretch behavior. You will need to change it, I will edit in a sec just on my mobile waiting for my laptop to boot up :)
Edit:
Er no ignore that I was thinking of ItemsControl, JBrooks is right, just make sure HorizontalContentAlignment is set to Stretch as the default is Left.
<ListView Name="ResultsView" HorizontalContentAlignment="Stretch">
That should work fine - any controls that use XXXXContentAlignment seem to default to Left which I think its a bit inconsistent vs other controls (such as Grid)
actually this is not a problem of Listview. Problem is where you are putting it in? Put your list view in grid. It should work
<ListView Name="ResultsView"
HorizontalContentAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Background="Yellow">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="4*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding BestRank}" Grid.Column="0"/>
<TextBlock Text="{Binding PlayerName}" Grid.Column="1"/>
<TextBlock Text="{Binding BestScore}" Grid.Column="2"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>