ActualWidth and ActualWidth is 0 - xaml

First of all YES I've read all the suggested "Questions that may already have your answer", so I belive this is not a dublicate.
I have this grid on a Page:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="70"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="Please sign below." Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Image x:Name="SignImage" />
</Grid>
<Grid Background="Transparent" Grid.Row="2" Margin="12,0,10,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="10"/>
</Grid.ColumnDefinitions>
<Button x:Name="ClearButton" Content="Clear" Grid.Column="1"/>
<Button x:Name="OkButton" Content="Ok" Grid.Column="2"/>
</Grid>
</Grid>
Then this CodeBehind:
public MainPage()
{
InitializeComponent();
this.Loaded += MainPage_Loaded;
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}
....
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
MessageBox.Show($"SignImage.ActualWidth: {SignImage.ActualWidth}, SignImage.ActualWidth: {SignImage.ActualWidth} ");
}
The problem is that the size of my Image is 0 (zero).
How do I make my Image fill out the cell I've placed it in?

First there is difference between * and Auto. Please do check the size of the main grid. "*" means stretch to fill the available space, and is a fraction, so if one row is * and the other row is 2* then the second row will be twice the size of the first row.
Auto means it takes whatever/or only space it needs.
If you have set the size of whole Grid to a small height then there will be a problem. Set the MinHeight for the Main Grid component.
Second you have not set the image for SignImage with a size which mean you will obviously get ActualWidth and ActualHeight as Zero. The image tag is empty in which no Source is set.
<Image x:Name="SignImage" Source="C:\Users\Administrator\Pictures\user-thumbnail.png"/>
Check after setting the image source if you are getting the ActualWidth and ActualHeight
Have a look at this image I have written your code. You can see that for Grid 0 and 2 there is Height set for Grid 1 there is no Height set as you have written * for it so it is necessary to set the height to parent.
Now look at this image I have set the height for the parent element as 200 and hence you can see the Gird 1 is visible and the height is not 0.
So it is necessary to set the height or set the image source for the height not to be zero.

Related

How do I set a proportional value for row height in a listView so it occupies the entire screen?

I need the items in my listView to have a height so it the list exactly fits the screen. Here's my code given below. I tried setting the Height of rows in my grid to a custom value, but that would work well, fitting the screen in some devices, while there would be an empty space in other devices due to a different screen size.
<ListView
ItemsSource="{Binding PenStocks}"
ItemSelected="Event_ItemSelected"
ItemTapped="Event_ItemTapped"
SeparatorVisibility="None"
Margin="5,5,5,0"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="9" ColumnSpacing="0" RowSpacing="0" HorizontalOptions="FillAndExpand" >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.408*"/>
<ColumnDefinition Width="0.051*"/>
<ColumnDefinition Width="0.252*"/>
<ColumnDefinition Width="0.033*"/>
<ColumnDefinition Width="0.153*"/>
<ColumnDefinition Width="0.102*"/>
</Grid.ColumnDefinitions>
What can I do for this? Please help me and thank you!
EDIT:
Rewrote this to use a bindablelayout.
View:
<StackLayout x:Name="ParentFlexLayout" BindableLayout.ItemsSource="{Binding Colors}" HorizontalOptions="FillAndExpand" >
<BindableLayout.ItemTemplate>
<DataTemplate>
<Frame BackgroundColor="{Binding .}" VerticalOptions="FillAndExpand"/>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
Here we use a bindablelayout - it's very flexible, so you could give it at go and see it it meets your needs
Codebehind:
public ObservableCollection<Color> Colors { get; set; } = new ObservableCollection<Color>();
public MainPage()
{
InitializeComponent();
BindingContext = this;
Colors.Add(Color.Blue);
Colors.Add(Color.Red);
Colors.Add(Color.Green);
Colors.Add(Color.Yellow);
}
Result:
If you want to your listViewItem to stretch to the height of it's inner control you can use
<RowDefinition Height="Auto"/>
It would be better if you share some screen shots.
Or you can check out the below post:
RowDefinition Height not working when using bound property on Grid in ListView?
I tried using an absolutelayout within the viewcell, but when I do, it doesn't work either.
<AbsoluteLayout AbsoluteLayout.LayoutBounds="0,0,1,0.167" AbsoluteLayout.LayoutFlags="All">

Xamarin.Forms: Tiny icons are getting cut ever so slightly when size is set with grid value

this is a simple grid with a tiny button in it:
<!--ReverseButton-->
<Grid Grid.Row="1" RowSpacing="0" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<ImageButton
Source="btn_reversed_unpressed"
x:Name="btn_reverse_list_mainmenu"
BackgroundColor="#00000000"
Grid.Column="1"
Clicked="ReverseListForSwipeView"
/>
</Grid>
The size of this Row (row 1) is set here:
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="0.17*" />
<RowDefinition Height="4.5*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
I set the value to 0.17* to have the button always be very tiny. If i would set the row to "auto" the icon would become much bigger (since the source image is bigger in size)
If I make the size to, lets say 0.25* instead of 0.17* the row and therefore the button both get bigger and everything is fine. (Except now it is too big)
But with size 0.17* it is just about right... Well except for this:
It is quite hard to see, but the icon at the bottom is cut of slightly. The border is not as big as it is on the top.
This I have noticed quite some time now.
I tried setting the rowspacing to 0 or even negative values, but nothing worked.
Why is the icon cut off.
The top part isnt cut and both parts (top and bottom) touch the row end and beginning pixel perfect.
An answer based on my comment above. I suggest setting the HeightRequest of the ImageButton to the size you want the icon to be and then just set the row height to Auto and let the layout manager do the rest. See my example where I create a Grid with 3 rows set to Auto size and then just use the HeightRequest property to have it draw at the correct size. I left the grey background of the button in so you can see how the row sizes dynamically.
<ContentPage.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ImageButton Source="ic_email_dark"
Aspect="AspectFit"
HeightRequest="50"
HorizontalOptions="Fill"
VerticalOptions="Center"
Grid.Row="0" />
<ImageButton Source="ic_email_dark"
Aspect="AspectFit"
HeightRequest="75"
HorizontalOptions="Fill"
VerticalOptions="Center"
Grid.Row="1" />
<ImageButton Source="ic_email_dark"
Aspect="AspectFit"
HeightRequest="100"
HorizontalOptions="Fill"
VerticalOptions="Center"
Grid.Row="2" />
</Grid>
</ContentPage.Content>
Gives the following:

Canvas causes contentcontrol children to spill out over control

I have the following XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="11" />
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<ListView ... Grid.Column="2"/>
<controls:GridSplitter
Grid.Column="1"
Width="11"
ResizeBehavior="BasedOnAlignment"
ResizeDirection="Auto"
Background="Gray"
Foreground="White"
FontSize="13">
<controls:GridSplitter.Element>
<Grid>
<TextBlock HorizontalAlignment="Center"
IsHitTestVisible="False"
VerticalAlignment="Center"
Text=""
Foreground="Black"
FontFamily="Segoe MDL2 Assets">
</TextBlock>
</Grid>
</controls:GridSplitter.Element>
</controls:GridSplitter>
<Canvas Canvas.ZIndex="1">
<ContentControl MaxWidth="750" Content="{Binding CAV, Mode=TwoWay}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" />
</Canvas>
</Grid>
Without the Canvas wrapped around the ContentControl in the first column, the children of the ContentControl properly stay within the content control and I can make it wider to see more of the children horizontally.
When I add the Canvas and set the ZIndex, the children of the content control spill out over the gridsplitter and the ListView without respecting the width of the contentcontrol.
The effect I'm trying to get it to allow expanding the width of the content control with the grid splitter and having that content control expand "over" the listview (instead of reducing the width of the listview).
What am I missing? I'm confused as to why the width of the contentcontrol isn't being respected suddenly just because I wrap it in a Canvas. Or should I not be using Canvas to get the "overlay" effect I want?
Canvas doesn't stretch its children. It only gives them the space they need. In fact, you don't have to wrap your ContentControl inside a Canvas to set the Canvas.ZIndex; it is an attached property that can be attached to the ContentControl directly. If you want a panel that allows its children/child to stretch, try a Border(single child only) or a Grid.
However, setting the ZIndex here seems to be unnecessary to me. Since the GridSplitter simply resizes the width of the columns, there won't be any overlay happening here.
If you want the overlay effect, you need to create another Grid with the same column layout and place your ListView there, something like the following -
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="11" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Grid x:Name="ListView" Background="LightGreen" Grid.Column="2" />
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="11" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<controls:GridSplitter Grid.Column="1" Background="LightBlue">
</controls:GridSplitter>
<Grid x:Name="ContentControl" Background="LightPink" Opacity="0.5" />
</Grid>
</Grid>
As an addendum Canvas tells the layout tree it uses no space. It doesn't care about the size of it's children, despite however many children it might have. For reference, here's the Canvas' MeasureOverride:
protected override Size MeasureOverride(Size constraint)
{
Size childConstraint = new Size(Double.PositiveInfinity, Double.PositiveInfinity);
foreach (UIElement child in InternalChildren)
{
if (child == null) { continue; }
child.Measure(childConstraint);
}
return new Size();
}
Which effectively says "I'm not taking up any space and my children can use whatever space they want".

Prevent Image from stretching beyond actual size

I have an Image control bound to a source. Here is what I want:
If the source image is smaller than the Grid containing it, it should display at its original size. It should not stretch beyond 100%. This is behavior of setting Stretch="None".
If the source image is larger than parent Grid, it should be resized uniformly to fit the container. This behavior is available with Stretch="Uniform".
I have tried to bind MaxWidth and MaxHeight to parent's actual dimensions as follows:
<DataTemplate x:Key="ImageDataTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Title}" Grid.Row="0"/>
<TextBlock Text="{Binding Type}" Grid.Row="1"/>
<Grid x:Name="ImageWrapper" Grid.Row="1" Tapped="ImageWrapper_Tapped" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="AliceBlue">
<Image Source="{Binding Link}" MaxWidth="{Binding ActualWidth, ElementName=ImageWrapper}" MaxHeight="{Binding ElementName=ImageWrapper, Path=ActualHeight}"/>
</Grid>
</Grid>
</DataTemplate>
However, I just end up with no image at all. Parent Grid occupies all available space as can be seen from background color. But there's no image.
Is there a way to achieve behavior I want?
Put the Image in a Viewbox control and set the Viewbox's StretchDirection to DownOnly. The Stretch property of the Viewbox has a default value of Uniform, so you don't need to set it.
<Viewbox StretchDirection="DownOnly">
<Image Source="{Binding Link}" Stretch="None"/>
</Viewbox>
Perhaps worth to note, in WPF you could directly set the StretchDirection of the Image control, and thus would not need a Viewbox.
<Image Source="{Binding Link}" StretchDirection="DownOnly"/>

Button fill inside grid column in Windows phone 8.1

I am new to Windows Phone development. I created a grid and added a button to one of the columns, the button does not fill the entire grid column. I am not even able to drag and resize the button control.
This is the code. The button appears at the center of column 0 and is cropped since it tries to fill into column2 as well. The same code seems to work fine in a 8.0 project I downloaded. Can anyone tell me how I can make the button fill the entire column and not spill into the second grid.
Updated code
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="0" Grid.Column="0">Text</Button>
<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="0" Grid.Column="1">Text</Button>
<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="0" Grid.Column="2">Text</Button>
<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="0" Grid.Column="3">Text</Button>
</Grid>
Try adding this to your Button.
HorizontalAlignment="Stretch"
In WP8.1, its default value is Left.
Update
The cut-off issue is because there's a default MinWidth (109) set to the default Button style.
Try removing it by doing this.
MinWidth="0"