How to add text to the shapes in WPF - c#

I am drawing Circle on an WPF window. The problem is that I am unable add Text to the Circle. The code is given below:
public Graphics()
{
InitializeComponent();
StackPanel myStackPanel = new StackPanel();
Ellipse myel = new Ellipse();
SolidColorBrush mscb = new SolidColorBrush();
mscb.Color = Color.FromArgb(255, 255, 0, 0);
myel.Fill = mscb;
myel.StrokeThickness = 2;
myel.Stroke = Brushes.Black;
myel.Width = 100;
myel.Height = 100;
//string str = "hello";
myStackPanel.Children.Add(myel);
this.Content = myStackPanel;
}
Please help me in this regard.

Shapes are simply shapes, if you want to add text then add both the shape and a TextBlock with your text to a common container which lays them on top of each other, e.g. a Grid without rows or columns.
In XAML:
<Grid>
<Ellipse Width="100" .../>
<TextBlock Text="Lorem Ipsum"/>
</Grid>
C#
var grid = new Grid();
grid.Children.Add(new Ellipse { Width = 100, ... });
grid.Children.Add(new TextBlock { Text = "Lorem Ipsum" });

Or you can use direct positioning in a Canvas if you prefer direct control over the draw position:
My sample defines a UI control that draws rectangles with text in it:
XAML:
<UserControl x:Class="DrawOnCanvas"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MySample"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Canvas x:Name="DrawCanvas" Height="30"/>
</Grid>
Code behind:
// You might e.g. call this in the constructor of DrawOnCanvas
internal void DrawRectWithText()
{
var rect = new System.Windows.Shapes.Rectangle();
rect.Stroke = new SolidColorBrush(Colors.Black);
rect.Fill = new SolidColorBrush(Colors.Beige);
rect.Width = 100;
rect.Height = 100;
// Use Canvas's static methods to position the rectangle
Canvas.SetLeft(rect, 100);
Canvas.SetTop(rect, 100);
var text = new TextBlock()
{
Text = task.Title,
};
// Use Canvas's static methods to position the text
Canvas.SetLeft(text, 90);
Canvas.SetTop(text, 90);
// Draw the rectange and the text to my Canvas control.
// DrawCanvas is the name of my Canvas control in the XAML code
DrawCanvas.Children.Add(rect);
DrawCanvas.Children.Add(text);
}

Related

How to fix DoubleAnimation for rotation of an image?

I am trying to rotate an image on an EventHandler, for an Event that i created. The Event Handler works perfectly fine. Yet the image does not rotate and I do not know what I am missing.
This UserControl is not displayed like this, but in a Grid of another UserControl.
<UserControl x:Class="Mabri.Module.P83.View.SchematicSystemView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Mabri.Module.P83.View"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Image x:Name="drehteller" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</UserControl>
This is the code behind the XAML, at first I tried having this in a separat class, if this is possible it would be even better, but at the moment I am just trying to get this running.
{
private System.Windows.Controls.Image drehteller_image;
private int currentAngle = 0;
public SchematicSystemView()
{
EventAggregator.SubscribeEvent(this);
InitializeComponent();
drehteller_image = new System.Windows.Controls.Image()
{
Stretch = Stretch.Uniform,
Source = new BitmapImage(new Uri("pack://application:,,,/Mabri.Module.P83;Component/Images/drehteller_unbestueckt.png")),
RenderTransform = new RotateTransform()
};
drehteller.Source = drehteller_image.Source;
}
public void OnEventHandler(DrehtellerMoved e)
{
EventAggregator.PublishEvent(new LogInfo
{
Title = "Should rotate",
Summary = "The drehteller should rotate now",
Detail = "The drehteller should rotate " + currentAngle + " is the current angle",
LogLevel = LogLevel.Information
});
int steps = e.steps;
double timeforonestep = e.speed / e.steps;
int angle = steps * 72;
int angle_to_reach = currentAngle + angle;
Storyboard storyboard = new Storyboard();
storyboard.Duration = new Duration(TimeSpan.FromSeconds(timeforonestep * steps));
DoubleAnimation rotateAnimation = new DoubleAnimation()
{
From = currentAngle,
To = currentAngle + angle,
Duration = storyboard.Duration
};
Storyboard.SetTarget(rotateAnimation, drehteller);
Storyboard.SetTargetProperty(rotateAnimation, new PropertyPath("(UIElement.RenderTransform).(RotateTransform.Angle)"));
storyboard.Children.Add(rotateAnimation);
storyboard.Begin();
currentAngle = angle_to_reach;
}
}
In the testing case e.steps equals 1 and e.speed equals 10.0.
I expected the image to turn for 72 degrees, but for some reasons nothing happens, except for the LogMessage at the beginning of the handler.
First, assign a RotateTransform to the RenderTransform property of the Image. Otherwise it can't be animated.
<Image x:Name="drehteller" HorizontalAlignment="Center" VerticalAlignment="Center"
RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<RotateTransform/>
</Image.RenderTransform>
</Image>
Then instead of setting From and To just set By. And drop the Storyboard and start the animation directly on the control's RenderTransform
var animation = new DoubleAnimation
{
By = angle,
Duration = TimeSpan.FromSeconds(...)
};
drehteller.RenderTransform.BeginAnimation(RotateTransform.AngleProperty, animation);
Finally, do not create the intermediate Image element. That is redundant.
drehteller.Source = new BitmapImage(new Uri("..."));

WPF Databound Grid Scaling

I want to bind data to a grid in xaml. This is the code I am using for binding it:
<Grid x:Name="Example" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<ContentPresenter Content="{Binding ExampleImage}" />
</Grid>
Now when I bind it using fixed width and height it will display the grid at set dimensions.
Code:
private Grid _exampleImage;
public Grid ExampleImage
{
get
{
if (SelectedSectie != null)
{
var convertFromString = System.Windows.Media.ColorConverter.ConvertFromString("#CCCCCC");
if (convertFromString != null)
{
DropShadowEffect dse = new DropShadowEffect
{
BlurRadius = 5,
ShadowDepth = 1,
Direction = 270,
Color =
(System.Windows.Media.Color)
convertFromString
};
_exampleImage = new Grid
{
Background =
new SolidColorBrush(SingleIcons.Helpers.ColorConverter.ToMediaColor(SelectedSectie.Color.ColorValue)),
VerticalAlignment = VerticalAlignment.Stretch,
Width = SelectedIconSize.Width,
Height = SelectedIconSize.Height,
MaxWidth = SelectedIconSize.Width,
MaxHeight = SelectedIconSize.Height,
HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch,
Effect = dse,
RowDefinitions =
{
new RowDefinition {Height = new GridLength(46, GridUnitType.Star)},
new RowDefinition {Height = new GridLength(3, GridUnitType.Star)}
}
};
}
TextBlock afbeeldingTextBlock = new TextBlock
{
Text = _selectedSectie.Sectie,
TextWrapping = TextWrapping.Wrap,
TextAlignment = TextAlignment.Center,
Width = _exampleImage.Width,
FontSize = Global.Fontsize,
FontFamily = new System.Windows.Media.FontFamily(Global.Family.Name),
VerticalAlignment = VerticalAlignment.Center,
Foreground =
new SolidColorBrush(
SingleIcons.Helpers.ColorConverter.ToMediaColor(SelectedSectie.Color.TextColorValue)),
};
TextOptions.SetTextFormattingMode(afbeeldingTextBlock, TextFormattingMode.Display);
TextOptions.SetTextRenderingMode(afbeeldingTextBlock, TextRenderingMode.ClearType);
Canvas bottomCanvas = new Canvas
{
Background = (SolidColorBrush) (new BrushConverter().ConvertFrom("#26000000"))
};
Grid.SetRow(afbeeldingTextBlock, 0);
Grid.SetRow(bottomCanvas, 1);
_exampleImage.Children.Add(afbeeldingTextBlock);
_exampleImage.Children.Add(bottomCanvas);
_exampleImage.Measure(new System.Windows.Size(_exampleImage.Width,
_exampleImage.Height));
_exampleImage.Arrange(
new Rect(new System.Windows.Size(_exampleImage.Width, _exampleImage.Height)));
return _exampleImage;
}
else
{
return null;
}
}
}
Now what I would like to do is to keep the grid at set dimensions but allow the GUI to scale the grid,
because when I make the window smaller the grid stays at these dimensions and it hurts the scaling of the application.
The reason I am using a databound grid is because I have another function which exports this grid to a .png.
Putting it inside a Viewbox and setting StretchDirection to DownOnly was the result i wanted.
<Grid x:Name="Example" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Viewbox StretchDirection="DownOnly" >
<ContentPresenter Content="{Binding ExampleImage}" />
</Viewbox>
</Grid>

Can WPF window contain a child ?

I have a WPF window:
<Window x:Class="Snapit.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" WindowState="Maximized"
ShowInTaskbar="True" AllowsTransparency="True" WindowStyle="None" Opacity="0.1"
BorderThickness="25" BorderBrush="Black" Name="myWindow">
<Grid Name="myGrid">
</Grid>
</Window>
And I have a rectangle
System.Windows.Shapes.Rectangle myRect = new System.Windows.Shapes.Rectangle();
myRect = new System.Windows.Shapes.Rectangle();
myRect.Stroke = System.Windows.Media.Brushes.Yellow;
myRect.Fill = System.Windows.Media.Brushes.Black;
myRect.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
myRect.VerticalAlignment = VerticalAlignment.Center;
myRect.Height = 50;
myRect.Width = 50;
myRect.Opacity = 100;
myWindow.AddChild(myRect);
But I am not able to add the rectangle as a child and the error come as :
{"'The invocation of the constructor on type 'Snapit.MainWindow' that matches the specified binding constraints threw an exception.' Line number '3' and line position '9'."}
I dont understand where I am going wrong. Thanks!!
Your window can have only one child, and it's your Grid...
If you want to do it, you should change
myWindow.AddChild(myRect);
to
myGrid.AddChild(myRect);
But, why didn't you use the xaml to write your rectangle ? It will be more clean to read it...
Add it to your Layout Grid not to Window,
Change this line,
From :myWindow.AddChild(myRect);
To :myGrid.AddChild(myRect);
Final Code:
System.Windows.Shapes.Rectangle myRect = new System.Windows.Shapes.Rectangle();
myRect = new System.Windows.Shapes.Rectangle();
myRect.Stroke = System.Windows.Media.Brushes.Yellow;
myRect.Fill = System.Windows.Media.Brushes.Black;
myRect.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
myRect.VerticalAlignment = VerticalAlignment.Center;
myRect.Height = 50;
myRect.Width = 50;
myRect.Opacity = 100;
myGrid.AddChild(myRect);

When typing text in textbox, keep background constant

I'm writing a program that starts out with requiring a certain amount of lines of text and for that I use a TextBox. To make the program look nice, I put a background image on the form. Now I don't want the TextBox to put a large white block on the image, so for that I made the TextBox have a transparent background. But here's the problem: as soon as I start putting text in the TextBox, the lines that have text will revert back to the white background that I don't want. So how can I stop my program from doing that?
I can't post images yet, so I'll just use links:
This image shows the background as I have it and how I want it to be:
This image shows what happens when I start typing:
I want the background to just remain the same while I type (of course the text colour should then be lighter, but the textbox.forecolor seems to have no effect.
So below is the code I have so far, I hope you can help me, I'm still quite new to this :)
public class NieuwSpel : Form
{
Label spelerslijst, nummer;
TextBox spelersInput, spelnr;
Button OK;
public NieuwSpel()
{
this.BackgroundImage = WeerwolvenvanWakkerdam.Properties.Resources.Background_NieuwSpel;
this.FormBorderStyle = FormBorderStyle.Fixed3D;
spelerslijst = new Label();
spelerslijst.Location = new Point(10, 10);
spelerslijst.Text = "Voer hier de spelerslijst in:";
spelerslijst.Width = 200;
spelerslijst.BackColor = Color.Transparent;
spelerslijst.ForeColor = Color.White;
this.Controls.Add(spelerslijst);
spelersInput = new CustomTextBox();
spelersInput.Location = new Point(10, 40);
spelersInput.Size = new Size(200, 300);
spelersInput.Multiline = true;
spelersInput.BackColor = Color.FromArgb(100, 100, 100, 100);
spelersInput.ForeColor = Color.White;
spelersInput.GotFocus += this.setColour;
this.Controls.Add(spelersInput);
OK = new Button();
OK.Text = "Start Spel!";
OK.Location = new Point(110, 430);
OK.Click += this.Start;
this.Controls.Add(OK);
nummer = new Label();
nummer.Text = "Spelnummer:";
nummer.Width = 75;
nummer.Location = new Point(10, 360);
nummer.BackColor = Color.Transparent;
nummer.ForeColor = Color.White;
this.Controls.Add(nummer);
spelnr = new CustomTextBox();
spelnr.Width = 50;
spelnr.Height = 20;
spelnr.Location = new Point(90, 360);
spelnr.BackColor = Color.FromArgb(100, 100, 100, 100);
spelnr.ForeColor = Color.White;
this.Controls.Add(spelnr);
}
public void setColour(object o, EventArgs ea)
{
((CustomTextBox)o).BackColor = Color.FromArgb(100, 100, 100, 100);
}
}
public partial class CustomTextBox : TextBox
{
public CustomTextBox()
{
SetStyle(ControlStyles.SupportsTransparentBackColor |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.ResizeRedraw |
ControlStyles.UserPaint, true);
}
}
This probably won't be easy in WinForms. If you're just messing around on your own and trying to learn, you might want to consider playing around with WPF. A lot of people still have to deal with WinForms, but I've developed in both and WPF definitely supersedes it.
It can provide the desired effect out-of-the-box:
<Window x:Class="SampleWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:SampleWpf"
Title="MainWindow" Height="250" Width="400" >
<Window.Background>
<ImageBrush ImageSource="images.jpg" />
</Window.Background>
<Grid>
<TextBox Margin="5" Background="Transparent" Text="HELLO THERE!"
FontSize="20" FontWeight="Bold" Foreground="White" />
</Grid>
</Window>

Dynamic Viewbox not Stretching

In my earlier example of Input Box, I have a window variable. I created some controls(Textbox, Label, Buttons). Parent of these controls is canvas. Parent of canvas is a ViewBox (because ViewBox can only contain one child) and parent of ViewBox is the window.
So hierarchy is like Window->Viewbox->Canvas-> Controls. All these control creation and parenting is done dynamically.
winInputDialog = new Window();
lblPrompt = new Label();
btnOK = new Button();
btnCancel = new Button();
txtInput = new TextBox();
cvContainer = new Canvas();
VB = new Viewbox();
//
// lblPrompt
//
lblPrompt.Background = new SolidColorBrush(SystemColors.ControlColor);
lblPrompt.FontFamily = new FontFamily("Microsoft Sans Serif");
lblPrompt.FontSize = 12;
lblPrompt.Background = new SolidColorBrush(Colors.Transparent);
lblPrompt.FontStyle = FontStyles.Normal;
lblPrompt.Margin = new Thickness(8, 9, 0, 0);
lblPrompt.Name = "lblPrompt";
lblPrompt.Width = 302;
lblPrompt.Height = 82;
lblPrompt.TabIndex = 3;
//
// btnOK
//
btnOK.Margin = new Thickness(322, 8, 0, 0);
btnOK.Name = "btnOK";
btnOK.Width = 64;
btnOK.Height = 24;
btnOK.TabIndex = 1;
btnOK.Content = "OK";
btnOK.Click += new RoutedEventHandler(btnOK_Click);
//
// btnCancel
//
btnCancel.Margin = new Thickness(322, 40, 0, 0);
btnCancel.Name = "btnCancel";
btnCancel.Width = 64;
btnCancel.Height = 24;
btnCancel.TabIndex = 2;
btnCancel.Content = "Cancel";
btnCancel.Click += new RoutedEventHandler(btnCancel_Click);
//
// txtInput
//
txtInput.Margin = new Thickness(8, 70, 0, 0);
txtInput.Name = "txtInput";
txtInput.Width = 379;
txtInput.Height = 25;
txtInput.TabIndex = 0;
//
//Canvas
//
double width = System.Windows.SystemParameters.PrimaryScreenWidth / 3, height = System.Windows.SystemParameters.PrimaryScreenHeight / 4;
cvContainer.Height = height;
cvContainer.Width = width;
cvContainer.Children.Add(txtInput);
cvContainer.Children.Add(btnCancel);
cvContainer.Children.Add(btnOK);
cvContainer.Children.Add(lblPrompt);
cvContainer.ClipToBounds = true;
//
//ViewBox
//
VB.Stretch = Stretch.Fill;
VB.Child = cvContainer;
//
// InputBoxDialog
//
winInputDialog.Width = width;
winInputDialog.Height = height;
winInputDialog.Content = VB;
winInputDialog.Icon = new System.Windows.Media.Imaging.BitmapImage(new System.Uri(System.IO.Directory.GetCurrentDirectory() + #"\drop-box-icon.png"));
winInputDialog.WindowStartupLocation = WindowStartupLocation.CenterScreen;
//winInputDialog.WindowStyle = WindowStyle.SingleBorderWindow;
winInputDialog.ResizeMode = ResizeMode.CanResizeWithGrip;
winInputDialog.Name = "InputBoxDialog";
I have set the width and height property of canvas equal to window. But why my screen look like this:
Why is there space between controls and window borders even though they are in viewbox. I even tried Cliptobounds but still the same.
If i set Viewbox height and width it does not stretch and behave unlike a Viewbox.
i want to set this screen dynamically. How?
Sample Project is at http://122.160.24.172/download/customer_data/InputBox_New.rar.
If you want your window to have a dynamic layout, why won't you use a dynamic container unlike Canvas which is static?
You could use a Grid like this -
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.8*"/>
<ColumnDefinition Width ="0.2*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="Hello"/>
<Button Grid.Column="1" Content="Ok"/>
<Button Grid.Row="1" Grid.Column="1" Content="Cancel"/>
<TextBox Grid.Row="2" Grid.ColumnSpan="2" Text="Hello"/>
</Grid>
This way your window will layout itself when its size is changed.
You can still adjust the button size and margin if you'd like.
Don't use a Canvas unless you really need support for exact pixel coordination positioning layout.
Also: Why are you layouting your window programatically and not in XAML?

Categories