Using a System.Drawing.Font with a WPF Label - wpf

I have a WPF Label control which I'm trying to change the appearance of using a System.Drawing.Font object supplied by some legacy code. I have been able to set most of the properties, but am struggling with Strikeout and Underline.
So far I have:
System.Drawing.Font font = FontFromLegacyCode();
System.Windows.Controls.Label label = new System.Windows.Controls.Label();
label.FontFamily = new System.Windows.Media.FontFamily( font.Name );
label.FontWeight = font.Bold ? System.Windows.FontWeights.Bold : System.Windows.FontWeights.Regular;
label.FontStyle = font.Italic ? System.Windows.FontStyles.Italic : System.Windows.FontStyles.Normal;
label.FontSize = font.Size;
How do you set the font strikeout or underline properties? Is there a better control to use?

I would change it to a TextBlock control. The TextBlock control has the TextDecorations property you can use.
<TextBlock Name="textBlock" TextDecorations="Underline, Strikethrough" />
Or you can stick a TextBlock inside a Label if you really like (although I'd just use the TextBlock by itself).
<Label Name="label">
<TextBlock Name="textBlock" TextDecorations="Underline, Strikethrough" />
</Label>
Have a look at the TextDecorations class.
I find that TextBlocks are more suitable than Labels in most situations. Here's a blog post about the differences. The chief difference being that a Label is a Control whereas a TextBlock is just a FrameworkElement. Also a Label supports access keys.

Looking at the code you already have, there might be a problem with it.
On the MSDN on Windows Form and WPF Property mapping they make the comment:
Font size in WPF is expressed as one ninety-sixth of an inch, and in Windows Forms as one seventy-second of an inch. The corresponding conversion is:
Windows Forms font size = WPF font size * 72.0 / 96.0.

Related

Vertical alignment of Label inside TextBlock is wrong

In a WPF popup window that I display to the user I want to put a text that is bound to a variable inside a block of text.
I've tried to do so by putting a <Label> inside a <TextBlock>.
However, this leads to alignment problems, see markup and picture below.
I wonder how I can get the text in the Label to align vertically with the text in the TextBlock, or if there is a better solution?
I could put the entire text in a variable, but then I don't know how to get <Bold> formatting for part of the text.
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap"
VerticalAlignment="Top" Height="99" Width="339" Grid.RowSpan="3">
The user is <Bold>responsible</Bold> for
<Bold><Label Content="00" Padding="0"/></Bold> vehicles
</TextBlock>
You can use the Run inline element for data binding text.
Starting in the .NET Framework 4, the Text property of the Run object is a dependency property, which means that you can bind the Text property to a data source.
It also has properties for styling the text, like FontWeight, no need for <Bold> here.
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap"
VerticalAlignment="Top" Height="99" Width="339" Grid.RowSpan="3">
The user is <Bold>responsible</Bold> for
<Run Text="{Binding YourProperty}" FontWeight="Bold"/> vehicles
</TextBlock>
The result looks like this:
As a general note on the issue: The elements inside TextBlock should be inline elements. Here is an article that has links to other inline elements that could be useful to you, like span that allows for grouping other inline elements and applying styles or to them.
How to: Manipulate Flow Content Elements through the Inlines Property
WPF has two fundamental base types, UIElement and ContentElement. While a TextBlock and Label are UIElements, the content of TextBlock are inlines, which are ContentElements. That is why the alignment is off, they serve very different purposes. You can read up more on the differences and concepts here:
Base Element APIs in WPF Classes
UIElement
UIElement is a base class for WPF core level implementations building on Windows Presentation Foundation (WPF) elements and basic presentation characteristics.
ContentElement
Provides a WPF core-level base class for content elements. Content elements are designed for flow-style presentation, using an intuitive markup-oriented layout model and a deliberately simple object model.
Flow Document Overview

WPF text control with colors only

I need a text control where the user is able to edit text and where some parts of the text can have different colors based on the text. Basically, imagine Visual Studio source file editor or any other source file editor which colors the source code. What WPF control is that? None of the three options in WPF I am aware of are not suitable:
TextBox doesn't allow colors
TextBlock doesn't allow users to edit the text
RichTextBox allows too much - I just want colors.
Maybe RichTextBox can have fixed other text formattings (i.e. fonts, bold, italic)? Any thoughts?
Here is a (very) rough example keeping stick with TextBox and TextBlock: just for fun, but worthwhile...
Here is the XAML...
<Grid>
<TextBlock
x:Name="Tx1"
HorizontalAlignment="{Binding Path=HorizontalAlignment, ElementName=Tb1}"
VerticalAlignment="{Binding Path=VerticalAlignment, ElementName=Tb1}"
Margin="{Binding Path=Margin, ElementName=Tb1}"
FontSize="{Binding Path=FontSize, ElementName=Tb1}"
/>
<TextBox
x:Name="Tb1"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Margin="100,0"
FontSize="24"
Background="Transparent"
Foreground="Transparent"
TextChanged="Tb1_TextChanged"
/>
</Grid>
...and here is some code...
private void Tb1_TextChanged(object sender, TextChangedEventArgs e)
{
var inlines = this.Tx1.Inlines;
inlines.Clear();
foreach (char ch in this.Tb1.Text)
{
if (Char.IsDigit(ch))
{
var run = new Run(ch.ToString());
run.Foreground = Brushes.Blue;
inlines.Add(run);
}
else if (Char.IsLetter(ch))
{
var run = new Run(ch.ToString());
run.Foreground = Brushes.Red;
inlines.Add(run);
}
else
{
var run = new Run(ch.ToString());
run.Foreground = Brushes.LimeGreen;
inlines.Add(run);
}
}
}
The trick is using a transparent TextBox over a TextBlock, which can be colored by collecting many different Run elements.
I think your best choice is looking for 3rd Party controls, as suggested by Erno.
For example: wpfsyntax
WPF Syntax Highlight Textbox is very simple control for editing source code. Contains line numbering, world highlighting, indenting (tab, shift+tab....) and more. Test application contains parser for language IronPython and Boo. Syntax Highlight Textbox is developed in C#.
Or: Fast colored textblox
For one of my projects, I have felt the need of a text editor with syntax highlighting. At first, I used a component inherited from RichTextBox, but while using it for a large amount of text I found out that RichTextBox highlights very slowly a large number of colored fragments (from 200 and more). When such highlighting has to be made in a dynamic way, it causes a serious problem.
Therefore I created my own text component which uses neither Windows TextBox nor RichTextBox.
This Feature is not in any of the text controls. May be you can write your own custom control by inheriting RichTextBox.

Make a silverlight textblock act like a hyperlink

I'm pretty new to silverlight. I have a text block that is displayed inside a datagrid
(inside a DataGridTemplateColumn.CellTemplate template to be precise).
I'd like to dynamically make some of the textblocks into hyperlinks that open a new window.
Is there a way to do this - so far all I can come up with is using a hyperlink button and trying to style it to look like a text block.
Any help would be very much appreciated.
HyperlinkButton is a ContentControl so it can actually take some kind of pre-styled TextBlock (or other control) as it's content (instead of just using a simple string as Content).
<HyperlinkButton NavigateUri="http://myurl.com">
<TextBlock Text="My Link Text" Foreground="Black" />
</HyperlinkButton>
You would have to use a custom HyperlinkButton template if you wanted to style it to get rid of the default teal colored focus ring, etc. You could also set the IsEnabled property of the HyperlinkButton to false to prevent link behavior on any cells that weren't actually links if you are trying to set them up in some dynamic way.

WPF Styles Question

A simple question which I can't find the answer on the web for some reason...
I want to place the content to a ResourceDictionary:
<TextBlock
Style="{StaticResource HomePageTextStyle}">
<LineBreak/>
Hello<LineBreak/>
<Bold>World!</Bold>
<LineBreak/>
</TextBlock>
The best I could do was:
<s:String x:Key="HomePageTextContent">
Hello World!
</s:String>
Which stripped all the formatting from the content :( Help please~ Thanks in advance. Oh, and If you can recommend a nice reference for using WPF Styles, it would be great~ Thanks!
I'd say you want to use data-binding instead of applying a style, since you are putting content in the TextBlock not changing the appearance of the TextBlock itself, e.g. drawing a border around it.
According to MSDN: TextBlock supports the hosting and display of Inline flow content elements. To be more precise, the content of the TextBlock in your first code block becomes a InlineCollection in the Inlines property of the TextBlock. Unfortunately the Inlines property isn't a dependency property so we can't bind data to it. The Text property, on the other hand, is a dependency property but doesn't allow anything other than a String.
To make a long story short, I don't think you can achieve what you want using pure XAML.

creating a nice GUI in WPF

I need to create a desktop CAD application which essentially should have a nice modern GUI.
I am thinking of creating a WPF application so that I can have a rich user interface.
Could some one suggest me a well designed desktop application GUI framework in WPF, please?
I found some cool GUI in this video http://channel9.msdn.com/posts/Psychlist1972/Pete-at-PDC09-WPF-3d-Awesomeness-with-Tor-and-Robby/
but not sure of the controls they used in their application.
Does any one have an idea which controls did they use there?
Is there any property grid control in WPF? I tried to use the grid in Windows Forms. Customizing this grid to suit my requirement seems to be difficult. It shows all the properties of the object straight from the very base class to the most derived.
With WPF, a lot is possible. You'll find a wide variety of looks to various applications due to the fact that, unlike Windows Forms, WPF can be templated and styled much like HTML. Actual designers can easily bring a look and feel which is very difficult to accomplish in Windows Forms. Naturally, since it is so flexible, the look of highly styled applications will vary a great deal from application to application.
That said, there are some very good 3rd party controls. All the usual suspects have control libraries for WPF: Telerik, Infragistics, ComponentOne, Actipro, Devxpress just to name a few. Specifically, Actipro's Property Grid is very nice. There is also an open source one which I haven't evaluated, so can't speak to. WPF can also be "themed" by applying pre-compiled styles to controls. There are example themes found here: http://wpfthemes.codeplex.com/.
Finally, WPF's strengths are not fully realized until you learn how to separate the view which gets drawn and managed by WPF and the logical abstraction of the view, called the view model. Josh Smith has a great article about this pattern, known as Model-View-ViewModel, here: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx.
I think Microsoft saw no point in including a PropertyGrid control in WPF because it is so trivial to create your own, and if they created the control it would be harder to style.
To create your own PropertyGrid, just use a <ListBox> with an <ItemsTemplate> that has a <DockPanel> containing a <TextBlock> docked to the left for the property name and a <ContentPresenter> for the value editor, then enable grouping on the Category property.
The only code you need to write is the code that reflects on the object and creates the list of properties.
Here is a rough idea of what you would use:
DataContext =
from pi in object.GetType().GetProperties()
select new PropertyGridRow
{
Name = pi.Name,
Category = (
from attrib in pi.GetCustomAttributes(false).OfType<CategoryAttribute>()
select attrib.Category
).FirstOrDefault() ?? "None",
Description = (
from attrib in pi.GetCustomAttributes(false).OfType<DescriptionAttribute>()
select attrib.Description
).FirstOrDefault(),
Editor = CreateEditor(pi),
Object = object,
};
The CreateEditor method would simply construct an appropriate editor for the property with a binding to the actual property value.
In the XAML, the <ListBox.ItemTemplate> would be something like this:
<DataTemplate>
<DockPanel>
<TextBlock Text="{Binding PropertyName}" Width="200" />
<ContentPresenter DataContext="{Binding Object}" Content="{Binding Editor}" />
</DockPanel>
</DataTemplate>
I'll let you fill in the rest of the details.

Resources