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.
Related
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.
I have a dynamically created WPF Canvas element inside a ContentControl (the same thing happens in a UserControl.) Whenever I attempt to set the background, either upon creation or later on in the program, the background color won't paint (I am however able to set the background on a Label inside of the Canvas (also added dynamically.) The creation code I have looks like:
_rootGrid = new Grid();
_rootGrid.Name = "_rootGrid";
_rootGrid.Margin = new Thickness(0);
_rootGrid.HorizontalAlignment = HorizontalAlignment.Stretch;
_rootGrid.VerticalAlignment = VerticalAlignment.Stretch;
_rootGrid.RowDefinitions.Add(new RowDefinition());
_rootGrid.RowDefinitions.Add(new RowDefinition());
_rootGrid.ColumnDefinitions.Add(new ColumnDefinition());
_rootGrid.RowDefinitions[0].Height = new GridLength(24);
_rootGrid.RowDefinitions[1].Height = new GridLength(0, GridUnitType.Star);
_rootGrid.ColumnDefinitions[0].Width = new GridLength(0, GridUnitType.Star);
_headerBlock = new Canvas();
_headerBlock.Name = "_headerBlock";
_headerBlock.SetValue(Grid.RowProperty, 0);
_headerBlock.SetValue(Grid.ColumnProperty, 0);
_headerBlock.PreviewMouseLeftButtonUp += _headerBlock_PreviewMouseLeftButtonUp;
_headerBlock.Background = Brushes.Red;
_title = new Label();
_title.Name = "_title";
_title.Content = "Title";
_title.VerticalAlignment = VerticalAlignment.Center;
_title.HorizontalAlignment = HorizontalAlignment.Left;
_title.FontWeight = FontWeights.Bold;
_title.Background = Brushes.Blue;
_clientBlock = new ScrollViewer();
_clientBlock.Name = "_clientBlock";
_clientBlock.Margin = new Thickness(0);
_clientBlock.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
_clientBlock.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
_clientBlock.SetValue(Grid.RowProperty, 1);
_clientBlock.SetValue(Grid.ColumnProperty, 0);
_clientArea = new Grid();
_clientArea.Name = "_clientArea";
_clientArea.HorizontalAlignment = HorizontalAlignment.Stretch;
_clientArea.VerticalAlignment = VerticalAlignment.Stretch;
_headerBlock.Children.Add(_title);
_rootGrid.Children.Add(_headerBlock);
_clientBlock.Content = _clientArea;
_rootGrid.Children.Add(_clientBlock);
base.Content = _rootGrid;
And is called inside of the ContentControl constructor. From that I would expect the header to contain a full row of Red with a Blue rectangle around the text, but all I get is the Blue rectangle around text with most of the row left Transparent (noticeable due to the Green background of the root Grid.) Any help on this would be appreciated as it is enormously frustrating. I'm using version 6.2 of the .NET framework on Windows 7 if that plays into it (I have noticed some other odd behaviors, but am going for dynamic generation mostly because these ContentControls take lots of child elements and the VS 2017 XAML parser is too broken to allow them to be named - which makes them virtually useless.)
The solution is to use non-zero Width for ColumnDefinition:
_rootGrid.ColumnDefinitions[0].Width = new GridLength(1, GridUnitType.Star); // equal to Width="*" in xaml
When 0 is used, Canvas has 0 witdh. But is is possible to see blue Label because Canvas doesn't clip contents on its bounds.
If you try Grid (var _headerBlock = new Grid();) with zero width column, there won't be anything displayed at all.
Currently my images just go down vertically, I want 4 images to display horizontally in each row, I've tried few suggestions on here but can't seem to get it working to work, its quite confusing to me as a beginner.
foreach (MyWCF.dogs c in lc)
{
RowDefinition row = new RowDefinition();
row.Height = new GridLength(1.0, GridUnitType.Auto);
g.RowDefinitions.Add(row);
StackPanel sp = new StackPanel();
sp.Orientation = Orientation.Horizontal;
BitmapImage image = new BitmapImage();
Image i1 = new Image();
using (InMemoryRandomAccessStream ms = new InMemoryRandomAccessStream())
{
using (DataWriter writer = new DataWriter(ms.GetOutputStreamAt(0)))
{
writer.WriteBytes((byte[])p.images);
writer.StoreAsync().GetResults();
}
//var image = new BitmapImage();
image.SetSource(ms);
}
i1.Source = image;
i1.Height = 100;
sp.Children.Add(i1);
Grid.SetRow(sp, gridRef);
g.Children.Add(sp);
gridRef++;
}
(Trying again with the Microsoft code explicitly included. I presume its OK to point to S.O. answers instead of copying an pasting the entirety of the S.O. answer here )
Perhaps the tutorial Grid Class : "Defines a flexible grid area that consists of columns and rows." will help. Then, this S.O. question Adding Image to Grid C# shows how to add images to a WPF grid.
Here is the material from the Grid Class post:
The following C# example demonstrates how to create a grid. In this case, the grid defines three ColumnDefinition elements and four RowDefinition elements that host child content.
// Create the application's main window
mainWindow = new Window();
mainWindow.Title = "Grid Sample";
// Create the Grid
Grid myGrid = new Grid();
myGrid.Width = 250;
myGrid.Height = 100;
myGrid.HorizontalAlignment = HorizontalAlignment.Left;
myGrid.VerticalAlignment = VerticalAlignment.Top;
myGrid.ShowGridLines = true;
// Define the Columns
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);
// Add the first text cell to the Grid
TextBlock txt1 = new TextBlock();
txt1.Text = "2005 Products Shipped";
txt1.FontSize = 20;
txt1.FontWeight = FontWeights.Bold;
Grid.SetColumnSpan(txt1, 3);
Grid.SetRow(txt1, 0);
// Add the second text cell to the Grid
TextBlock txt2 = new TextBlock();
txt2.Text = "Quarter 1";
txt2.FontSize = 12;
txt2.FontWeight = FontWeights.Bold;
Grid.SetRow(txt2, 1);
Grid.SetColumn(txt2, 0);
// Add the third text cell to the Grid
TextBlock txt3 = new TextBlock();
txt3.Text = "Quarter 2";
txt3.FontSize = 12;
txt3.FontWeight = FontWeights.Bold;
Grid.SetRow(txt3, 1);
Grid.SetColumn(txt3, 1);
// Add the fourth text cell to the Grid
TextBlock txt4 = new TextBlock();
txt4.Text = "Quarter 3";
txt4.FontSize = 12;
txt4.FontWeight = FontWeights.Bold;
Grid.SetRow(txt4, 1);
Grid.SetColumn(txt4, 2);
// Add the sixth text cell to the Grid
TextBlock txt5 = new TextBlock();
Double db1 = new Double();
db1 = 50000;
txt5.Text = db1.ToString();
Grid.SetRow(txt5, 2);
Grid.SetColumn(txt5, 0);
// Add the seventh text cell to the Grid
TextBlock txt6 = new TextBlock();
Double db2 = new Double();
db2 = 100000;
txt6.Text = db2.ToString();
Grid.SetRow(txt6, 2);
Grid.SetColumn(txt6, 1);
// Add the final text cell to the Grid
TextBlock txt7 = new TextBlock();
Double db3 = new Double();
db3 = 150000;
txt7.Text = db3.ToString();
Grid.SetRow(txt7, 2);
Grid.SetColumn(txt7, 2);
// Total all Data and Span Three Columns
TextBlock txt8 = new TextBlock();
txt8.FontSize = 16;
txt8.FontWeight = FontWeights.Bold;
txt8.Text = "Total Units: " + (db1 + db2 + db3).ToString();
Grid.SetRow(txt8, 3);
Grid.SetColumnSpan(txt8, 3);
// Add the TextBlock elements to the Grid Children collection
myGrid.Children.Add(txt1);
myGrid.Children.Add(txt2);
myGrid.Children.Add(txt3);
myGrid.Children.Add(txt4);
myGrid.Children.Add(txt5);
myGrid.Children.Add(txt6);
myGrid.Children.Add(txt7);
myGrid.Children.Add(txt8);
// Add the Grid as the Content of the Parent Window Object
mainWindow.Content = myGrid;
mainWindow.Show ();
I using following code, When I run below code, Half of the text only displayed in label box. I want display full line in label box text? How to do it?
Label dynamiclabel1 = new Label();
dynamiclabel1.Location = new Point(280, 90);
dynamiclabel1.Name = "lblid";
dynamiclabel1.Size = new Size(150, 14);
dynamiclabel1.Text="Smith had omitted the paragraph in question (an omission which had escaped notice for twenty years) on the ground that it was unnecessary and misplaced; but Magee suspected him of having been influenced by deeper reasons.";
dynamiclabel1.AutoSize = true;
dynamiclabel1.Font = new Font("Arial", 10, FontStyle.Regular);
panel1.Controls.Add(dynamiclabel1);
Label dynamiclabel = new Label();
dynamiclabel.Location = new Point(38, 30);
dynamiclabel.Name = "lbl_ques";
dynamiclabel.Text = question;
//dynamiclabel.AutoSize = true;
dynamiclabel.Size = new System.Drawing.Size(900, 26);
dynamiclabel.Font = new Font("Arial", 9, FontStyle.Regular);
You have used AutoSize and explicit label size setting at the same time, this makes no sense.
If you want to enable word wrapping in your label text - you have to set dynamiclabel1.AutoSize = false; first and then increase its Height. Currently it has only 14 pixels of height so it is impossible to make text multiline. Increase it to something about 200 pixels and all the text will be placed inside the label in a few lines.
If you increase the height, and want less rows, set the Width property to something bigger;
dynamiclabel1.Width = 150;
If you want to select the number of lines depending on font/text size, you can do something like this:
Label dynamiclabel1 = new Label();
dynamiclabel1.Location = new Point(280, 90);
dynamiclabel1.Name = "lblid";
dynamiclabel1.Size = new Size(150, 100);
dynamiclabel1.Text = "Smith had omitted the paragraph in question (an omission which had escaped notice for twenty years) on the ground that it was unnecessary and misplaced; but Magee suspected him of having been influenced by deeper reasons.";
dynamiclabel1.Font = new Font("Arial", 10, FontStyle.Regular);
int lines = 3; //number of lines you want your text to display in
using (Graphics g = CreateGraphics())
{
SizeF size = g.MeasureString(dynamiclabel1.Text, dynamiclabel1.Font);
float w=size.Width / lines;
dynamiclabel1.Height = (int)Math.Ceiling(size.Height*lines);
dynamiclabel1.Width = (int)Math.Ceiling(w);
}
panel1.Controls.Add(dynamiclabel1);
Edit
If what you know is the width you have available and you want your label to adjust height to show all the content, can do this:
Label dynamiclabel1 = new Label();
dynamiclabel1.Location = new Point(280, 90);
dynamiclabel1.Name = "lblid";
dynamiclabel1.Size = new Size(150, 100);
dynamiclabel1.Text = "Smith had omitted the paragraph in question (an omission which had escaped notice for twenty years) on the ground that it was unnecessary and misplaced; but Magee suspected him of having been influenced by deeper reasons.";
dynamiclabel1.Font = new Font("Arial", 10, FontStyle.Regular);
int width = 600; //Width available to your label
using (Graphics g = CreateGraphics())
{
SizeF size = g.MeasureString(dynamiclabel1.Text, dynamiclabel1.Font);
lines = (int)Math.Ceiling(size.Width / width);
dynamiclabel1.Height = (int)Math.Ceiling(size.Height * lines);
dynamiclabel1.Width = width;
}
panel1.Controls.Add(dynamiclabel1);
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 };