Dynamic width column xaml won't work - c#

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.

Related

Xaml Responsive DataGrid with Scroll Bar

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.

Grid row auto-size relative sizing issue

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)

How to navigate to specifically position on ListBox Windows Phone 8.1

i have a listbox with a lot of items, and each items when clicked go to a new page, what i want is when i return from the second page, stay at the same position of the item is clicked!
Thats my list!
<ListBox x:Name="list" Loaded="ListView_Loaded" SelectedItem="true" SelectionChanged="searchResultsList_SelectionChanged" ItemsSource="{Binding}" Background="{x:Null}">
<!--<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Margin" Value="0,0,0,15" />
</Style>
</ListView.ItemContainerStyle>-->
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Width="80" Height="80">
<Image Source="{Binding Caminho}" />
</Border>
<StackPanel Margin="0,16,0,0" Grid.Column="2">
<TextBlock Foreground="White" Text="{Binding NomeCurso}" TextWrapping="Wrap" FontSize="{StaticResource TextStyleExtraLargeFontSize}" />
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
thanks!
If you are using WinRT you can write the following code in your page constructor to cache it, this way the positions will be intact after you go back to this page:
this.NavigationCacheMode = NavigationCacheMode.Required;
And from your sample I cant really see if you are using ListBox or ListView, I will presume ListView which is better as the ListBox is somewhat not needed anymore.
One thing I also noticed is that you use a simple {Binding} for your ItemsSource so maybe it is reset every time you go back because of this (if you are doing something that does this, as this is not visible from your sample code). I always have an additional property of type ObservableCollection and bind to it for example ItemsSource={Binding MyItems}. This way the list is reset only when I reset the property MyItems.

Grid alternate color

I am trying to display a Grid with alternating color each other row. The best would be alternating template all together to be able to change the whole row.
To make sure there is no misunderstanding when i mean grid i mean grid, not datagrid, not gridview, grid as in <Grid></Grid>
Right now the only viable solution i have found was to make a grid with the appropriate amount of rows i want and in each rows i put another grid with 1 row and the 3 columns i need and copy pasted for each row by changing the back color. As you can see this is not very clean solution.
So i have looked around and found that the listbox can have the alternate count and on a simple trigger it can change everything and that was perfect until i noticed the highlight CANNOT be disabled. You can change the highlight brush but it override an alternate color so both cannot be used at the same time. Before you asked yes i did use the transparent bush and transparent is NOT really transparent, All it does is that it shows the color underneath the ListBox control which was the beige color of the canvas underneath and the item itself disappear.
Anyone know a way to apply a template of alternating row on a grid. Putting a simple style on the RowDefinition would be easy but since you can't really tell the type of element you put in a grid i doubt there is something that can be done as easy as that.
EDIT:
here my latest change. a little bit "cleaner"
i created 2 style for item control for each color theme like
<Style x:Key="PropertyGrid" TargetType="ItemsControl">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="2"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
</Grid>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="AlternatePropertyGrid" TargetType="ItemsControl">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Grid Background="#FFEBEBEB">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="2"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
</Grid>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
Then i used a stack panel and listed each line
<StackPanel>
<ItemsControl Style="{StaticResource PropertyGrid}">
<Label Content="Identifier" Style="{StaticResource PropertyNameLabel}"/>
<Label Content="{Binding ElementName=cboActions, Path=SelectedItem.UniqueIdentifier}" Style="{StaticResource PropertyValueLabel}"/>
<Rectangle Style="{StaticResource PropertyGridSplitter}"/>
</ItemsControl>
<ItemsControl Style="{StaticResource AlternatePropertyGrid}">
<Label Content="Source" Style="{StaticResource AlternatePropertyNameLabel}"/>
<Label Name="lblSource" Style="{StaticResource AlternatePropertyValueLabel}"/>
<Rectangle Style="{StaticResource AlternatePropertyGridSplitter}"/>
</ItemsControl>
<ItemsControl Style="{StaticResource PropertyGrid}">
<Label Content="Description" Style="{StaticResource PropertyNameLabel}"/>
<Label Name="lblActionDescription" Style="{StaticResource PropertyValueLabel}"/>
<Rectangle Style="{StaticResource PropertyGridSplitter}"/>
</ItemsControl>
</StackPanel>
each item in their respective style they have the grid column preset so style determine the location in the grid of each object within the item control.
It works but still i feel like there is probably a more efficient way to do it. here's a screenshot of what it look like right now, might be more helpful for the visual people to know what i am trying to achieve here.
With a Datagrid, you can easily do that :
<DataGrid AlternatingRowBackground="Blue"/>
With a grid, no idea :p
For a listbox inside the Grid, we set alternate colors with a some lines of code (code-behind).
private void SetAlternateColor()
{
var blueBrush = new SolidColorBrush(Colors.Blue);
var redBrush = new SolidColorBrush(Colors.Red);
for (int i = 0; i < Items.Count; i++)
{
ListBoxItem item = TestListBox.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem;
item.Background = i % 2 == 0 ? blueBrush : redBrush;
}
}
private void TestGrid_Loaded(object sender, RoutedEventArgs e)
{
SetAlternateColor();
}
Don't know if this is what you are looking for.
Repeating the code was fastest solution.

Windows 8 - XAML - Putting Grid Inside ListView

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>

Categories