Need to add text to rectangle - c#

I am creating Dynamic Rectangle and adding into StackPanel. I need to add text to each rectangle. How can I do that?

A Rectangle doesn't have any child content, so you will need to put both controls inside of another panel, such as a grid:
<Grid>
<Rectangle Stroke="Red" Fill="Blue"/>
<TextBlock>some text</TextBlock>
</Grid>
You can also use a Border control, which will take a single child and draw a rectangle around it:
<Border BorderBrush="Red" BorderThickness="1" Background="Blue">
<TextBlock>some text</TextBlock>
</Border>
You say "dynamic rectangle", so it sounds like you are doing this in code. The equivalent C# would look something like this:
var grid = new Grid();
grid.Children.Add(new Rectangle() { Stroke = Brushes.Red, Fill = Brushes.Blue });
grid.Children.Add(new TextBlock() { Text = "some text" });
panel.Children.Add(grid);
// or
panel.Children.Add(new Border()
{
BorderBrush = Brushes.Red,
BorderThickness = new Thickness(1),
Background = Brushes.Blue,
Child = new TextBlock() { Text = "some text" },
});
But if you want a dynamic list of rectangles, you should probably use an ItemsControl:
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Red" BorderThickness="1" Background="Blue">
<TextBlock Text="{Binding Text}"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
If you set the DataContext to a list of objects, this XAML will create a Border with a TextBlock for each one with the text set to the Text property on the object.

First of all you can do this, but not by adding the control. And there is a very good reason to do this, for high speed hardware rendering. You can create a special brush from a UI element that caches itself in hardware and fill the rectangle with this hardware, and it is extremely fast. I will just show the code behind because it is the example I have offhand
Rectangle r = new Rectangle();
r.Stroke = Brushes.Blue;
r.StrokeThickness = 5;
r.SetValue(Grid.ColumnProperty, 1);
r.VerticalAlignment = VerticalAlignment.Top;
r.HorizontalAlignment = HorizontalAlignment.Left;
r.Margin = new Thickness(0);
r.Width = 200;
r.Height = 200;
r.RenderTransform = new TranslateTransform(100, 100);
TextBlock TB = new TextBlock();
TB.Text = "Some Text to fill";
// The next two magical lines create a special brush that contains a bitmap
// rendering of the UI element that can then be used like any other brush
// and it's in hardware and is almost the text book example for utilizing
// all hardware rending performances in WPF unleashed 4.5
BitmapCacheBrush bcb = new BitmapCacheBrush(TB);
r.Fill = bcb;
MyCanvas.Children.Add(r);

You need to add a textual control to your StackPanel, such as Label or TextBlock.

Related

Add Text to a System.Windows.Shapes.Shape Code Behind,

I need to return a Text as a System.Window.Shapes Shape (dont ask why, its the task). Since there is no Text-Shape, I thought I could add a Text to an transparent Rectangle, but turns out, with all what I found on the net, the produced text just does not look nice but what is even worse: its drawn with some nasty artefacts:
It kind of looks like the upper top of the Text is cut and appended at the bottom (like some overflow of text)
this is the way I've done it (Need to add text to rectangle):
Rectangle r = new Rectangle();
r.Stroke = Brushes.Transparent;
r.StrokeThickness = 1;
r.VerticalAlignment = VerticalAlignment.Top;
r.HorizontalAlignment = HorizontalAlignment.Left;
r.Margin = new Thickness(0);
r.Width = 200;
r.Height = 200;
r.RenderTransform = new TranslateTransform(100, 100);
TextBlock TB = new TextBlock();
TB.Text = "TEST";
var ft = new FormattedText(
TB.Text,
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface("Verdana"),
16,
Brushes.Black);
r.Width = ft.Width;
r.Height = ft.Height;
//The next two magical lines create a special brush that contains a bitmap rendering of the UI element that can then be used like any other brush and its in hardware and is almost the text book example for utilizing all hardware rending performances in WPF unleashed 4.5
BitmapCacheBrush bcb = new BitmapCacheBrush(TB);
r.Fill = bcb;
Can somebody explain why this is happening and maybe give a workaround? Tried to play with Thickness, Padding, etc. but it didnt give the desired result.
I would appreciate any help! Thanks already
It's very easy to achieve what you want using MVVM and datatemplates. Below is a simplified demo to give you idea.
xaml:
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type local:TextItem}">
<TextBlock Text="{Binding Text}" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:ShapeItem}">
<ContentControl Content="{Binding Shape}" />
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Left}" />
<Setter Property="Canvas.Top" Value="{Binding Top}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
cs:
public class Item
{
public double Left { get; set; }
public double Top { get; set; }
}
public class ShapeItem : Item
{
public Shape Shape { get; set; }
}
public class TextItem : Item
{
public string Text { get; set; }
}
public partial class MainWindow : Window
{
public List<object> Items { get; } = new List<object>
{
new ShapeItem { Shape = new Rectangle { Width = 100, Height = 100, Fill= Brushes.Yellow, Stroke = Brushes.Red }, Left = 10, Top = 10 },
new TextItem { Text= "Lalala", Left = 50, Top = 50 },
};
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
}
Here is the output:
It's not 100% MVVM (for the sake of simplicity), but idea is to have different data template for text and for shapes. They have different viewmodels: TextItem and ShapeItem and are visualized as TextBlock or ContentControl correspondingly.
Another thing is to use ItemsControl to be able to bind to collection of Items and set Canvas.Left/Canvas.Top properties.
ToDo: use ObservableCollection, implement INotifyPropertyChanged for viewmodels, do not use view elements in the viewmodel (brushes, shapes, etc.).
As much as I appreciate all the answers given, I've found the solution:
simply set the fontsize of the Textblock to the same size that you use in formattedText to calculate the Text width and Height:
tb.Fontsize = 16;
...
this way not only does the text "overflow" disappear, but the text looks nice and sharp

Create "table style" ListView in UWP and XAML (C#)

I'm wondering if there is any way I can create a "table like" ListView in a UWP Windows 10 app? I need some sort of table where I can allow a user to browse and select files and then put the selected files into a list, sort of like a details view that you see in Windows explorer with column headers and rows that I can insert programmatically like:
string[] item = { "D:\\Music\\MyAudioFile.mp3", "MP3", "12MB" }
listview1.Items.Add(item);
Anyone have any ideas what I can use for this?
Thanks
Thanks Lindexi, that pointed me in the right direction... Here is the code I got working...
C# backend code:
// Create a new StackPanel to insert as a ListViewItem
StackPanel myStack = new StackPanel();
myStack.HorizontalAlignment = HorizontalAlignment.Stretch;
myStack.VerticalAlignment = VerticalAlignment.Stretch;
myStack.Orientation = Orientation.Horizontal;
// Create new StackPanel "Child" elements with alignment and width
ListViewItem lv1 = new ListViewItem();
lv1.Content = "Test Content";
lv1.Width = 400;
lv1.HorizontalAlignment = HorizontalAlignment.Stretch;
lv1.VerticalAlignment = VerticalAlignment.Stretch;
// Create new StackPanel "Child" elements with alignment and width
ListViewItem lv2 = new ListViewItem();
lv2.Content = "Test Content";
lv2.Width = 100;
lv2.HorizontalAlignment = HorizontalAlignment.Stretch;
lv2.VerticalAlignment = VerticalAlignment.Stretch;
// Create new StackPanel "Child" elements with alignment and width
ListViewItem lv3 = new ListViewItem();
lv3.Content = "Test Content";
lv3.Width = 100;
lv3.HorizontalAlignment = HorizontalAlignment.Stretch;
lv3.VerticalAlignment = VerticalAlignment.Stretch;
// Create new StackPanel "Child" elements with alignment and width
ListViewItem lv4 = new ListViewItem();
lv4.Content = "Test Content";
lv4.Width = 100;
lv4.HorizontalAlignment = HorizontalAlignment.Stretch;
lv4.VerticalAlignment = VerticalAlignment.Stretch;
// Create new StackPanel "Child" elements with alignment and width
ListViewItem lv5 = new ListViewItem();
lv5.Content = "Test Content";
lv5.Width = 250;
lv5.HorizontalAlignment = HorizontalAlignment.Stretch;
lv5.VerticalAlignment = VerticalAlignment.Stretch;
// Create new StackPanel "Child" elements with alignment and width
ListViewItem lv6 = new ListViewItem();
lv6.Content = "Test Content";
lv6.Width = 250;
lv6.HorizontalAlignment = HorizontalAlignment.Stretch;
lv6.VerticalAlignment = VerticalAlignment.Stretch;
// Add "Child" elements for the new StackPanel
myStack.Children.Add(lv1);
myStack.Children.Add(lv2);
myStack.Children.Add(lv3);
myStack.Children.Add(lv4);
myStack.Children.Add(lv5);
myStack.Children.Add(lv6);
// Add the new StackPanel as a ListViewItem control
MusicQueue.Items.Insert(1, myStack);
XAML Code:
<ListView Name="MusicQueue" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ListViewItem HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Orientation="Horizontal">
<ListViewHeaderItem Width="400">Filename</ListViewHeaderItem>
<ListViewHeaderItem Width="100">Format</ListViewHeaderItem>
<ListViewHeaderItem Width="100">Size</ListViewHeaderItem>
<ListViewHeaderItem Width="100">Duration</ListViewHeaderItem>
<ListViewHeaderItem Width="250">Artist</ListViewHeaderItem>
<ListViewHeaderItem Width="250">Title</ListViewHeaderItem>
</StackPanel>
</ListViewItem>
</ListView>
Of course this is probably not going to be the most efficient way to manually add an item to a ListView stacked horizontally, but it works which is most important :)
If anyone does know a quicker way to do this with less code please let me know :)
Thanks guys
You can use dataGrid in UWP.
But you also can use DataTemplate in ListView, and you can use blow code to solve the width is too small.
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment"
Value="Stretch"></Setter>
</Style>
</ListView.ItemContainerStyle>
The lib you can use is :https://github.com/MyToolkit/MyToolkit/wiki/DataGrid
And https://liftcodeplay.com/2015/10/24/datagrid-alternatives-in-uwp/
If you can spend money, you can use https://www.syncfusion.com/products/uwp/sfdatagrid

Stackpanel "breaks" and has black background when the content is side is too much

I have the follow XAML:
<ContentControl HorizontalAlignment="Left" HorizontalContentAlignment="Left" Content="{Binding TotalReviewWordBlock}" Width="465" Margin="5,10,0,5" Foreground="#FF2D2D2D" Background="White"/>
and its binded to the following property:-
public StackPanel TotalReviewWordBlock
{
get
{
StackPanel st = new StackPanel();
st.Orientation = Orientation.Horizontal;
st.Background = new SolidColorBrush(Colors.White);
Paragraph pgf = new Paragraph();
Run r = new Run();
r.Text = App.Convert("Blah ");
r.FontWeight = FontWeights.Bold;
r.Foreground = new SolidColorBrush(CommonLib.rgbFromHexString("#FF2D2D2D"));
pgf.Inlines.Add(r);
int Rating = (int)(this.userrating * 2);
string ratingReplacement;
(some more code in the property itself...)
Run run = new Run();
run.Text = " " + this.myText;
run.Foreground = new SolidColorBrush(CommonLib.rgbFromHexString("#FF2D2D2D"));
pgf.Inlines.Add(run);
RichTextBox rtb = new RichTextBox();
rtb.TextWrapping = TextWrapping.Wrap;
rtb.Width = 450;
rtb.Blocks.Add(pgf);
st.Children.Add(rtb);
st.Background = new SolidColorBrush(Colors.White);
return st;
}
}
The problem is when the text is too much(say more that a 1000 character), or the height of the stackpanel is a lot, Its background becomes black. Its as if the stackpanel breaks) I noticed this earlier but at that time it was in a listbox and had multiple items to i simply made the width of each item 480, used blank grids instead of margins and it was "covered". But this time its just one big chunk of text(in a Paragraph). Let me know if you need ay other info. Please help!!
I worked around a similar "black stackpanel" problem by splitting the text into paragraphs to form a List<String>. And then that list of strings would be the ItemsSource of a ListBox.
So instead of a very large StackPanel, I ended up with a long ListBox.
I also prevented user interaction in the ListBox and vertical scroll by using IsHitTestVisible="False" and ScrollViewer.VerticalScrollBarVisibility="Disabled"
So, the ListBoxended up as follows:
<ListBox x:Name="listBox" IsHitTestVisible="False" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Background="White">
<TextBlock TextWrapping="Wrap" Text="{Binding}"/>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And in code behind:
textSplitInParagraphs = new List<String>();
// add paragraphs to the list...
listBox.ItemsSource = textSplitInParagraphs;
Don't know if it is the correct workaround, but I helped me, after some time of banging my head against the table.
Hope this helps.

Assign image source in code-behind of XAML control

I have the following xaml
<StackPanel x:Name="StackPanelBanner" Grid.Row="1"></StackPanel>
I had to write this much messy code to add picture to it.
var toplogoBitmap = new BitmapImage();
toplogoBitmap.BeginInit();
toplogoBitmap.UriSource = new Uri(#"" + _appPath + "images/toplogo.png", UriKind.RelativeOrAbsolute);
toplogoBitmap.EndInit();
var toplogoImage = new Image
{
Source = toplogoBitmap,
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Left,
Stretch = Stretch.None
};
StackPanelBanner.Children.Add(toplogoImage);
Because i have to get the images from folder, which will be changing on time to time, i can't put them in resources.
Is there any short way of adding picture in XAML control. i.e
<StackPanel source="toplogo" x:Name="StackPanelBanner" Grid.Row="1"></StackPanel>
in Codebehind
var toplogo = #"" + _appPath + "images/toplogo.png";
Your "messy" code is pretty much the code you would need to add an item to a content control. You can't really shorten it, but if you're doing this regularly, refactoring to a method could help reduce the extra code required:
public void AddImageToContainer(string path, Panel parent)
{
var bmap = new BitmapImage(new Uri(_appPath + path, UriKind.RelativeOrAbsolute));
var img = new Image
{
Source = bmap,
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Left,
Stretch = Stretch.None
};
parent.Children.Add(img);
}
You could then just call this as needed, ie:
AddImageToContainer("images/toplogo.png", StackPanelBanner);
You could use an ItemsControl that uses a StackPanel as its ItemsPanel.
<ItemsControl x:Name="itemsControl" Grid.Row="1">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You might now add images as easy as shown below, because WPF provides built-in type conversion from string (or Uri) to ImageSource:
itemsControl.Items.Add(_appPath + "images/toplogo.png");

Items in StackPanel and columns

I'm adding controls dynamically to the StackPanel but all of them are aligned vertically and the items overpass the limit of the Height and not all items are displaying.
Is possible to align the controls based on the height and put it in several columns depending the number and height of the items?
<ScrollViewer Grid.Column="2" x:Name="DetailInfoScroll" Margin="25,0,50,0" Style="{StaticResource HorizontalScrollViewerStyle}" >
<StackPanel Grid.Column="2" Margin="25,0,50,35" HorizontalAlignment="Left" VerticalAlignment="Center" x:Name="StkText">
</StackPanel>
</ScrollViewer>
Adding the controls:
foreach (var text in texts)
{
StkText.Children.Add(new TextBlock
{
Text = text,
TextWrapping = TextWrapping.Wrap,
TextAlignment = TextAlignment.Justify,
FontSize = 14,
Margin = new Thickness(0, 0, 0, 25)
});
}
I found a solution using VariableSizedWrapGrid
http://msdn.microsoft.com/library/windows/apps/br227651.aspx
I think what you asking for is called WrapPanel. I hope I am not wrong. :)
Check those links out:
http://msdn.microsoft.com/en-us/library/system.windows.controls.wrappanel.aspx
http://msdn.microsoft.com/en-us/library/ms754152.aspx

Categories

Resources