Rotated textblock doesn't have the correct length - c#

I am trying to fill a Grid in a WPF application dynamically.
I'm creating a row and then some columns. in each column I am adding a textblock, like this:
GrdMainGrid.RowDefinitions.Add(new RowDefinition(Height = new GridLength(150, GridUnitType.Pixel);
GrdMainGrid.RowDefinitions.Add(new RowDefinition(Height = new GridLength(1, GridUnitType.Star);
for(var i=0; i<4; i++)
{
GrdMainGrid.ColumnDefinitions.Add(new ColumnDefinition {With = new GridLength(25, GridUnitType.Pixel)});
}
var header = new TextBlock {Text = "Header1", RenderTransform = new RotateTransform(-90), Width = 150, Margin = new Thickness(0), VerticalAlignment = VerticalAlignment.Bottom, HorizontalAlignment = HorizontalAlignment.Left};
.
.
.
Grid.SetColumn(header, 0);
Grid.SetRow(header, 0);
.
.
.
GrdMainGrid.Children.Add(header);
The textblock is rotated -90 degree.
While the size of the column is set to 25 pixel i doesn't show all text, when I increase the size of the column the text in textblock is also increased. see pic
I could understand this if the textblock wasn't rotated and it didn't fit in the column. But what has it to do with the size of the column when it's rotated.
And is it possible somehow to decrease the width of the column without decreasing size of text ?
Tnx in advance.

Use a LayoutTransform instead of a RenderTransform.
var header = new TextBlock { Text = "Header1", LayoutTransform = new RotateTransform(-90), Width = 150, Margin = new Thickness(0), VerticalAlignment = VerticalAlignment.Bottom, HorizontalAlignment = HorizontalAlignment.Left };

Related

Xamarin.Forms Images Causes Grid Row Height To Excessively Increase

The grid is already instantiated with the columns at the start of the code outside the foreach loop, within this loop, rows are being instantiated.
foreach (var post in posts)
{
Frame featuredFrame = new Frame();
featuredFrame.Padding = 20;
featuredFrame.Margin = new Thickness(0, 10, 0, 0);
Label postTitle = new Label();
postTitle.FontSize = Device.GetNamedSize(NamedSize.Subtitle, typeof(Label));
BoxView titleSeparator = new BoxView();
titleSeparator.Color = Color.Gray;
titleSeparator.HeightRequest = 1;
titleSeparator.HorizontalOptions = LayoutOptions.Fill;
Image postFeaturedImage = new Image();
postFeaturedImage.Source = ImageSource.FromUri(imageUri);
postFeaturedImage.Aspect = Aspect.AspectFill;
BoxView imageSeparator = new BoxView();
imageSeparator.Color = Color.Gray;
imageSeparator.HeightRequest = 2;
imageSeparator.HorizontalOptions = LayoutOptions.Fill;
Label publishDate = new Label();
publishDate.FontSize = Device.GetNamedSize(NamedSize.Caption, typeof(Label));
StackLayout postDetails = new StackLayout();
postDetails.Children.Add(postTitle);
postDetails.Children.Add(titleSeparator);
postDetails.Children.Add(postFeaturedImage);
postDetails.Children.Add(imageSeparator);
postDetails.Children.Add(publishDate);
postDetails.Margin = new Thickness(0);
postDetails.Padding = new Thickness(0);
featuredFrame.Content = postDetails;
postGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
postGrid.Children.Add(featuredFrame, columnNumber, rowNumber);
}
As you can see, the rows are being created with the height set to Auto, this should mean the rows are the same height as the children.
This is the result of the code above:
This is the result of the code above with postDetails.Children.Add(postFeaturedImage); commented out:
In the screenshot with the images, there is a lot of blank space below the publish date-time text. In the screenshot without the images, this blank space is gone.
I need the pictures visible, but the blank space shouldn't be there. How can I fix this?
I ran into the same issue (that's how I found the question) and I have managed to fix it.
I solved the problem by adding VerticalOptions like this:
postDetails.VerticalOptions = LayoutOptions.Start;
and make sure that you have Height = GridLength.Auto for the RowDefinition.

align image to the right inside a button programmatically WPF

I'm trying to align a image inside a button to the right. however it does not seem to do what i want it to do. i have been trying for several hours now, so i think it is time to ask here. this is my code atm.
public class DirectoryButton : Button
{
public DirectoryButton(string name, string content)
{
Name = name.Replace(" ", "");
//Content = new BitmapImage(new Uri("../Resources/folder-icon.png", UriKind.Relative)) + content;
//Content = new BitmapImage(new Uri("../Resources/folder-icon.png", UriKind.Relative));
var img = new BitmapImage(new Uri("../Resources/folder-icon.png", UriKind.Relative));
var sp = new UniformGrid
{
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
Columns = 3,
Rows = 1
};
sp.Children.Add(new Label());
sp.Children.Add(new Label { Content = content, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center });
sp.Children.Add(new Image { Source = img, HorizontalAlignment = HorizontalAlignment.Right, VerticalAlignment = VerticalAlignment.Center});
//sp.Orientation = Orientation.Horizontal;
Content = sp;
//Content = content;
Margin = new Thickness(0, 5, 0, 5);
Height = 65;
Width = 350;
FontWeight = FontWeights.Bold;
Foreground = new SolidColorBrush(Colors.Black);
Background = new SolidColorBrush(Colors.Gray);
HorizontalContentAlignment = HorizontalAlignment.Center;
VerticalAlignment = VerticalAlignment.Center;
Visibility = Visibility.Visible;
}
}
button Image
this makes the image in the button appear but it is not to the right. i cannot really do anything in the xaml since everything is created programmaticaly.
Regards,
Bjorn
Set the HorizontalContentAlignment to Stretch:
public class DirectoryButton : Button
{
public DirectoryButton(string name, string content)
{
Name = name.Replace(" ", "");
//Content = new BitmapImage(new Uri("../Resources/folder-icon.png", UriKind.Relative)) + content;
//Content = new BitmapImage(new Uri("../Resources/folder-icon.png", UriKind.Relative));
var img = new BitmapImage(new Uri("../Resources/folder-icon.png", UriKind.Relative));
var sp = new UniformGrid
{
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
Columns = 3,
Rows = 1
};
sp.Children.Add(new Label());
sp.Children.Add(new Label { Content = content, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center });
sp.Children.Add(new Image { Source = img, HorizontalAlignment = HorizontalAlignment.Right, VerticalAlignment = VerticalAlignment.Center });
//sp.Orientation = Orientation.Horizontal;
Content = sp;
//Content = content;
Margin = new Thickness(0, 5, 0, 5);
Height = 65;
Width = 350;
FontWeight = FontWeights.Bold;
Foreground = new SolidColorBrush(Colors.Black);
Background = new SolidColorBrush(Colors.Gray);
HorizontalContentAlignment = HorizontalAlignment.Stretch; //<--
VerticalAlignment = VerticalAlignment.Center;
Visibility = Visibility.Visible;
}
This should make the UniformGrid stretch to fill the entire Button and the Image will then end up to the right.
As I tried to explain in the comments above.
The code you've provide us works like it should.
You create an UniformGrid with three cells and add three childs to the grid.
Each cell of the grid will have the same size.
Your empty label will got to the left one. The next label to the center.
You will add your image to the right cell and set HorizontalAlignment = HorizontalAlignment.Right. This will align your image within his cell at the right edge. And also to the right edge of your grid.
Now you add your UniformGrid as Content to your button.
With the following line of code
HorizontalContentAlignment = HorizontalAlignment.Center;
you will center your grid within the button.
That's why your image is not at the right edge of your button.
As already suggested in my comment you can set
HorizontalContentAlignment = HorizontalAlignment.Right;
and your Image and the whole grid will move to the right edge, but this means also that your centered Label will also move to the right.
If you want to let the second Label stay within the center of the Button take the Answer provided by mm8 and use
HorizontalContentAlignment = HorizontalAlignment.Stretch;

C# WPF how to draw a circle which extends to fill its parent and remains a circle in code behind

I have to draw a circle in a grid. That grid has to adapt proportionally to height and width defined by the Column/Row definition of its parent grid.
Now if I put stretch it will fill all the space and become an ellipsis while I want it to be a circle.
Ok in short the parent grid adapts proportionally like that
then in a routine I add the following code:
public void RadialPercentage(Grid grd )
{
Ellipse elpExt = new Ellipse();
elpExt.Stroke = Brushes.Green;
elpExt.StrokeThickness = 4;
//elpExt.Margin = new Thickness(0);
//elpExt.HorizontalAlignment = HorizontalAlignment.Center;
elpExt.VerticalAlignment = VerticalAlignment.Stretch;
grd.Children.Add(elpExt);
Ellipse elpInt = new Ellipse();
elpInt.Stroke = Brushes.Blue;
elpInt.StrokeThickness = 4;
elpInt.Margin = new Thickness(20);
//elpInt.Width = elpInt.Height = dim-20;
//elpInt.HorizontalAlignment = HorizontalAlignment.Center;
elpInt.VerticalAlignment = VerticalAlignment.Stretch;
grd.Children.Add(elpInt);
return;
}
but the effect is the following:
so it stretches both vertically and horizontally even if I only put the vertical and not the horizontal constraint. If I set it to center the ellipse collapses.
To solve the problem even I am not sure that this is the right thing to do I tried to take a look of the weight/heigth of the parent grid but obviously both those values and the actual values are set to zero.
thanks for helping
Patrick
What about setting Width's binding to ActualHeight of the ellipse and set HorizontalAlignment to Center? Something like this:
var ellipse = new Ellipse();
var binding = new Binding(Ellipse.ActualHeightProperty.Name)
{
RelativeSource = new RelativeSource(RelativeSourceMode.Self),
Mode = BindingMode.OneWay
};
ellipse.VerticalAlignment = VerticalAlignment.Stretch;
ellipse.HorizontalAlignment = HorizontalAlignment.Center;
BindingOperations.SetBinding(ellipse, Ellipse.WidthProperty, binding);
You can update the size of your Ellipse each time the parent Grid is resized.
You should add to your Grid the SizeChanged Event. XAML example:
<Grid Name = "MyGrid"
SizeChanged = "MyGridSizeChanged">
<!-- rows and columns definitions -->
<Ellipse Name = "MyEllipse"
Grid.Row = "i"
Grid.Column = "j" />
</Grid>
Now, each time the Grid is resized the function MyGridSizeChanged will executed. You should add into it code, which set sizes of your Ellipse equal to smallest side of contained cell. C# example:
void MyGridSizeChanged(object sender, SizeChangedEventArgs e) {
if (sender is Grid myGrid) {
var cellHeight = myGrid.RowDefinitions[Grid.GetRow(MyEllipse)].ActualHeight;
var cellWidth = myGrid.ColumnDefinitions[Grid.GetColumn(MyEllipse)].ActualWidth;
var newSize = Math.Min(cellHeight, cellWidth);
MyEllipse.Height = newSize;
MyEllipse.Width = newSize;
}
}

TextWrap AND TextTrimming in a "flying" grid

I want to create a LiveTile. The text that will be displayed comes from a different backend so I don't have access or control. So I wanted to prerender the text (like this: http://developer.nokia.com/community/wiki/Custom_Live_Tile_with_Formatted_Text).
But I wanted to go 1 step further and Wrap and Trim the string as it MIGHT become longer.
A short version of the code is:
var wbmp = new WriteableBitmap();
var grid = new Grid();
grid.Width = pWidth;
grid.Height = pHeight;
var tblk = new TextBlock();
tblk.Text = pString;
tblk.Width = pWidth; // 691 or 336
tblk.Height = pHeight; // 336
tblk.TextTrimmin = TextTrimming.WordEllipsis;
tblk.TextWrappin = TextWrapping.Wrap;
grid.Children.Add(tblk);
wbmp.Render(grid, null);
wbmp.Invalidate();
This didn't trim the string. Then I read a bit about grids and texttrimming and I already have one xaml-part that does wirk woth both Oo So I did something like this:
var rowDef = new RowDefinition();
rowDef.Height = GridLength(1, GridUnitType.Auto);
grid.RowDefinitions.Add(rowDef);
rowDef = new RowDefinition();
rowDef.Height = GridLength(1, GridUnitType.Star);
grid.RowDefinitions.Add(rowDef);
tblk.SetValue(Grid.RowProperty, 0); // or 1 // or Grid.SetRow(tblk, 1);
and tried different combinations of Rows and Columns, Auto, Pixel and Stars. But nothing works. As the grid is not bound to anything else, "is flying" in the void, it doesn't create multiple rows. If I copy the same text in 4 colours and put it in 4 rows it only shows the upper one, because all others are exactly underneath..
What am I missing here? It can't be impossible to Trim and Wrap at the same time Oo
You have to call the Measure and Arrange methods of the UIElement to actually get the desired image. So here is the full code:
var grid = new Grid();
grid.Width = 80;
grid.Height = 80;
var tblk = new TextBlock();
tblk.Text = "Long enough text to show you text wrapping and trimming at the same time in this example.";
tblk.Width = 80;
tblk.Height = 80;
tblk.TextTrimming = TextTrimming.WordEllipsis;
tblk.TextWrapping = TextWrapping.Wrap;
grid.Children.Add(tblk);
grid.Measure(new Size(80, 80));
grid.Arrange(new Rect(0, 0, 80, 80));
grid.InvalidateVisual();
var renderTargetBitmap = new RenderTargetBitmap(80, 80, 96, 96, PixelFormats.Default);
renderTargetBitmap.Render(tblk);
After that you can use the renderTargetBitmap as a Source for an Image element, and you will see that the text is both trimmed and wrapped.

How to set height (in multiples of *) of a WPF grid cell programatically?

I have to set height of a CELL inside WPF Grid programmatically, based on values in a List or ObservableCollection. Mind that I want to set height of a CELL not ROW.
Note that the grid is generated programmatically
Grid myGrid = new Grid();
ColumnDefinition colDef1 = new ColumnDefinition();
ColumnDefinition colDef2 = new ColumnDefinition();
ColumnDefinition colDef3 = new ColumnDefinition();
myGrid.ColumnDefinitions.Add(colDef1);
myGrid.ColumnDefinitions.Add(colDef2);
myGrid.ColumnDefinitions.Add(colDef3);
// Define the Rows
RowDefinition rowDef1 = new RowDefinition();
RowDefinition rowDef2 = new RowDefinition();
RowDefinition rowDef3 = new RowDefinition();
RowDefinition rowDef4 = new RowDefinition();
myGrid.RowDefinitions.Add(rowDef1);
myGrid.RowDefinitions.Add(rowDef2);
myGrid.RowDefinitions.Add(rowDef3);
myGrid.RowDefinitions.Add(rowDef4);
Each cell of the grid contains either textboxes or borders as shown below.
ColumnDefinition column = new ColumnDefinition();
myGrid.ColumnDefinitions.Add(column);
Border b = new Border();
b.BorderBrush = Brushes.Black;
b.BorderThickness = new Thickness(2);
b.Padding = new Thickness(10);
TextBlock txt3 = new TextBlock();
txt3.Text = "Hello";
txt3.FontSize = 12;
txt3.FontWeight = FontWeights.Bold;
txt3.TextWrapping = TextWrapping.Wrap;
txt3.Margin = new Thickness(2);
Grid.SetColumn(txt3,2);
b.Child = txt3;
//Grid.SetColumn(txt3, 2);
//Grid.SetRowSpan (txt3,2);
//myGrid.Children.Add(txt3);
Grid.SetColumn(b, 2);
Grid.SetRowSpan(b, 2);
myGrid.Children.Add(b);
This makes no sense. How could you have a cell with a different height than the row? That just won't work.
You should just set the height on the RowDefinition for the row of that cell.
First of all you have to note, that setting a cell height more than row, will lead to cell cut off.
The second thing is that, there are no cell's, imagine Grid as a 2 dimensional array - you can set only content - if content overflows there are two possible ways - cell's content will be cut off or RowHeight will be increased based on the highest content in a row - the same for Columns.
Maybe if you would provide us with graphical example of what you are filling into the table, and why should cell's height increase, we would help you to find appropriate solution.
But now, you are going a wrong way...

Categories

Resources