How to auto align controls with Windows Forms - winforms

I have a simple form with a label inside and I changed the label font and size. Every time that I run the program the label gets out of the forms even trying to set the ContentAlignment.TopCenter. How can I make the label adjust to the current window?
Cs :
InitializeComponent();
this.FormBorderStyle = FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.label1.Font = new Font("Arial", 27, FontStyle.Regular);
this.label1.TextAlign = ContentAlignment.TopCenter;
label1.Text = "AAAAA BBBBB CCCCC DDDDD";

Please check if the label1's location property was set
Reset the location property to 0 using the Properties window or using the below line of code.
this.label1.Location = new Point(0, 0);

Related

WPF event within a frame stored on a stackpanel

I need to recreate a program similar to whatsapp that can send and receive messages, images videos and audio. I have created a WPF form to show messages that looks like this:
I have a stack panel that contains text bubbles on them. Text messages work fine but if I send an image I want the user to be able to click on the image text bubble and it must become full screen. The image text bubble consists of a label that has a frame in it and then within that frame the image is stored. The label was used since we could resize the label.
However, because the image is done like this dynamically, we cannot seem to register an on-click event on this image bubble. If you have any better ways that we can display the image or how to log this event it would be much appreciated. Here is the method used to add the image.
public void AddMessage_Image(string path, string displayName, int role, string date = "")
{
//Create an image from the path
ImageBrush image = new ImageBrush();
image.ImageSource = new BitmapImage(new Uri(path, UriKind.Absolute));
image.Stretch = Stretch.Uniform;
//Create a frame in which to place the image
Frame fr = new Frame();
fr.Background = image;
fr.MinHeight = 120;
fr.MinWidth = 160;
//Ensure scalabilty of the image
Viewbox vb = new Viewbox();
vb.Child = fr;
vb.Stretch = Stretch.Uniform;
//Place the image in a sizable container
Label lbl = new Label();
lbl.MinHeight = 10;
lbl.MinWidth = 10;
lbl.MaxHeight = 300;
lbl.MaxWidth = 400;
lbl.Content = vb;
if (role == (int) Role.Sender)
lbl.HorizontalAlignment = HorizontalAlignment.Right;
else
lbl.HorizontalAlignment = HorizontalAlignment.Left;
lbl.Background = Brushes.Black;
//Place the image in the chat
chatbox.Children.Add(lbl);
}

How to format specific text in WPF?

I have this code that adds dotted lines under text in text box:
// Create an underline text decoration. Default is underline.
TextDecoration myUnderline = new TextDecoration();
// Create a linear gradient pen for the text decoration.
Pen myPen = new Pen();
myPen.Brush = new LinearGradientBrush(Colors.White, Colors.White, new Point(0, 0.5), new Point(1, 0.5));
myPen.Brush.Opacity = 0.5;
myPen.Thickness = 1.0;
myPen.DashStyle = DashStyles.Dash;
myUnderline.Pen = myPen;
myUnderline.PenThicknessUnit = TextDecorationUnit.FontRecommended;
// Set the underline decoration to a TextDecorationCollection and add it to the text block.
TextDecorationCollection myCollection = new TextDecorationCollection();
myCollection.Add(myUnderline);
PasswordSendMessage.TextDecorations = myCollection;
My problem is I need only the last 6 characters in the text to be formatted!
Any idea how can I achieve that?
Instead of setting the property on the entire TextBlock, create a TextRange for the last six characters and apply the formatting to that:
var end = PasswordSendMessage.ContentEnd;
var start = end.GetPositionAtOffset(-6) ?? PasswordSendMessage.ContentStart;
var range = new TextRange(start, end);
range.ApplyPropertyValue(Inline.TextDecorationsProperty, myCollection);
If PasswordSendMessage is a TextBox rather than a TextBlock, then you cannot use rich text like this. You can use a RichTextBox, in which case this technique will work but you will need to use PasswordSendMessage.Document.ContentEnd and PasswordSendMessage.Document.ContentStart instead of PasswordSendMessage.ContentEnd and PasswordSendMessage.ContentStart.
You could databind your text to the Inlines property of TextBox and make a converter to build the run collection with a seperate Run for the last 6 characters applying your decorations

Silverlight programmatically binding from C# code

I have a Canvas and a custom control called BasicShape
After I add two BasicShape controls on the Canvas, I want programatically to connect them with a Line and I want to do this using the Binding class.
I want to connect the Bottom side of first shape with the Top side of the second one.
Initially i tried to connect only the X1 property of the Line with the Canvas.Left attached property of the fisrt BasicShape but this doesn't work. Line X1 property is not updated when I change the Canvas.SetLeft(basicShape1) value
BasicShape bs1 = canvas.Children[0] as BasicShape;
BasicShape bs2 = canvas.Children[1] as BasicShape;
Line line = new Line();
line.StrokeThickness = 1;
line.Stroke = new SolidColorBrush(Colors.Red);
line.X1 = 100;
line.Y1 = 100;
line.X2 = 200;
line.Y2 = 200;
canvas.Children.Add(line);
Binding b = new Binding("AnyName");
b.Source = bs1;
b.Path = new PropertyPath(Canvas.LeftProperty);
line.SetBinding(Line.X1Property, b);
I'm trying to create a simple UML diagram like this one
alt text http://www.invariant-corp.com/omechron/images/uml_diagram.gif
I just did it other way, without binding
This will be a permanent link
http://calciusorin.com/SilverlightDiagrams/
I decided to manually update all lines on shape Location or Size changed
private void basicShape_BasicShapeLocationSizeChangedEvent(BasicShape sender)
{
foreach (CustomLine customLine in lines)
{
if (customLine.StartFromShape(sender))
{
Point point = sender.GetLinePoint(customLine.GetStartSide());
customLine.SetStartPoint(point);
}
if (customLine.EndInShape(sender))
{
Point point = sender.GetLinePoint(customLine.GetEndSide());
customLine.SetEndPoint(point);
}
}
}
I am sure that the Binding solution is more elegant. Anyone interested in my solution, with SL Controls that can be resized, connected with lines, just contact me.

WPF - Text box that grows vertically to accommodate all text

The problem: I am not getting a textbox setting that will have a horizontally wordwrap and vertically auto grow functionality. I wish to do that by writing a code. I have written following code that creates a text box at mouse dblclick with wordwrap:
TextBox text2 = new TextBox();
text2.Width = 500;
text2.Visibility = Visibility.Visible;
text2.Focus();
text2.Height = 30;
text2.HorizontalAlignment = HorizontalAlignment.Left;
text2.VerticalAlignment = VerticalAlignment.Top;
Point p = e.GetPosition(LayoutRoot);
text2.Margin = new Thickness(p.X, p.Y, 0, 0);
LayoutRoot.Children.Add(text2);
But, textbox does not grow vertically.
Can somebody suggest me a code in C# to do exactly what I desire?
try using this
Grid grid = new Grid();
grid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
grid.RowDefinitions.Add(new RowDefinition());
TextBox textBox = new TextBox() { Width = 100, TextWrapping = TextWrapping.Wrap };
textBox.SetValue(Grid.RowProperty, 0);
grid.Children.Add(textBox);
window.Content = grid;
where window is the Name assigned to Window(root).
One way to accomplish the growth you're looking for is to use a string measuring mechanism which you would run any time the text in your text box changes. Simply measure and resize your text box accordingly with any change to the contents.
Have you tried this?
text2.Height = double.NaN; // or don't set the property, but some custom styles might give a default value ..
text2.TextWrapping = TextWrapping.Wrap;
text2.MinHeight = 30; // or not if you want the styles default
instead of
text2.Height = 30;
not setting it or using double.NaN is the same as using 'Auto' in xaml.

Printing a WPF FlowDocument

I'm building a demo app in WPF, which is new to me. I'm currently displaying text in a FlowDocument, and need to print it.
The code I'm using looks like this:
PrintDialog pd = new PrintDialog();
fd.PageHeight = pd.PrintableAreaHeight;
fd.PageWidth = pd.PrintableAreaWidth;
fd.PagePadding = new Thickness(50);
fd.ColumnGap = 0;
fd.ColumnWidth = pd.PrintableAreaWidth;
IDocumentPaginatorSource dps = fd;
pd.PrintDocument(dps.DocumentPaginator, "flow doc");
fd is my FlowDocument, and for now I'm using the default printer instead of allowing the user to specify print options. It works OK, except that after the document prints, the FlowDocument displayed on screen has changed to to use the settings I specified for printing.
I can fix this by manually resetting everything after I print, but is this the best way? Should I make a copy of the FlowDocument before I print it? Or is there another approach I should consider?
yes, make a copy of the FlowDocument before printing it. This is because the pagination and margins will be different. This works for me.
private void DoThePrint(System.Windows.Documents.FlowDocument document)
{
// Clone the source document's content into a new FlowDocument.
// This is because the pagination for the printer needs to be
// done differently than the pagination for the displayed page.
// We print the copy, rather that the original FlowDocument.
System.IO.MemoryStream s = new System.IO.MemoryStream();
TextRange source = new TextRange(document.ContentStart, document.ContentEnd);
source.Save(s, DataFormats.Xaml);
FlowDocument copy = new FlowDocument();
TextRange dest = new TextRange(copy.ContentStart, copy.ContentEnd);
dest.Load(s, DataFormats.Xaml);
// Create a XpsDocumentWriter object, implicitly opening a Windows common print dialog,
// and allowing the user to select a printer.
// get information about the dimensions of the seleted printer+media.
System.Printing.PrintDocumentImageableArea ia = null;
System.Windows.Xps.XpsDocumentWriter docWriter = System.Printing.PrintQueue.CreateXpsDocumentWriter(ref ia);
if (docWriter != null && ia != null)
{
DocumentPaginator paginator = ((IDocumentPaginatorSource)copy).DocumentPaginator;
// Change the PageSize and PagePadding for the document to match the CanvasSize for the printer device.
paginator.PageSize = new Size(ia.MediaSizeWidth, ia.MediaSizeHeight);
Thickness t = new Thickness(72); // copy.PagePadding;
copy.PagePadding = new Thickness(
Math.Max(ia.OriginWidth, t.Left),
Math.Max(ia.OriginHeight, t.Top),
Math.Max(ia.MediaSizeWidth - (ia.OriginWidth + ia.ExtentWidth), t.Right),
Math.Max(ia.MediaSizeHeight - (ia.OriginHeight + ia.ExtentHeight), t.Bottom));
copy.ColumnWidth = double.PositiveInfinity;
//copy.PageWidth = 528; // allow the page to be the natural with of the output device
// Send content to the printer.
docWriter.Write(paginator);
}
}
You can use the code from the URL below, it wraps the flow document in a fixed document and prints that, the big advantage is that you can use it to add margin, headers and footers.
https://web.archive.org/web/20150502085246/http://blogs.msdn.com:80/b/fyuan/archive/2007/03/10/convert-xaml-flow-document-to-xps-with-style-multiple-page-page-size-header-margin.aspx
The following works with both text and non-text visuals:
//Clone the source document
var str = XamlWriter.Save(FlowDoc);
var stringReader = new System.IO.StringReader(str);
var xmlReader = XmlReader.Create(stringReader);
var CloneDoc = XamlReader.Load(xmlReader) as FlowDocument;
//Now print using PrintDialog
var pd = new PrintDialog();
if (pd.ShowDialog().Value)
{
CloneDoc.PageHeight = pd.PrintableAreaHeight;
CloneDoc.PageWidth = pd.PrintableAreaWidth;
IDocumentPaginatorSource idocument = CloneDoc as IDocumentPaginatorSource;
pd.PrintDocument(idocument.DocumentPaginator, "Printing FlowDocument");
}
I am also generating a WPF report off a Flow document, but I am purposely using the flow document as a print preview screen. I there for want the margins to be the same. You can read about how I did this here.
In your scenario I'm thinking why not just make a copy of your settings, instead of the entire flow document. You can then re-apply the settings if you wish to return the document back to it's original state.

Resources