Silverlight and Unexpected Font Sizes - silverlight

Someone please teach me to fish here...
I'm just learning Silverlight and have ran into a few situations where the font size actually used is drastically different than I would expect. There's probably something conceptual that I'm missing.
Case A
In one instance, I have defined a user control that presents a Label to show text. If one clicks on the label, the label (that is in a stack panel, in the user control) is replaced with a TextBox. When used at the top of a page (as in the example below with lblName) the label text is very small (around 8 points). When clicked on, the text box that replaces the label uses the specified fonts size. That same user control, used in different parts of the app, uses the same font for Label and TextBox.
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="33" />
<RowDefinition Height="267*" />
</Grid.RowDefinitions>
<StackPanel Height="Auto" HorizontalAlignment="Left" Name="stackPanel" VerticalAlignment="Top" Width="Auto" Grid.Row="1" />
<my:EditLabel Height="33" HorizontalAlignment="Left" x:Name="lblName" VerticalAlignment="Top" Width="Auto" FlexText="{Binding Name, Mode=TwoWay}" FontSize="20" MinHeight="24" />
</Grid>
Case B
I'm using the LiquidMenu.Menu control to pop up a menu when a button is pressed. The font looks huge compared to the rest of my page (maybe 36 points?). I tried forcing it to a very small by explicitly setting it to 8pt, but that had no effect.
<Grid x:Name="LayoutRoot" Background="{x:Null}">
<StackPanel x:Name="labelStackPanel" Orientation="Horizontal">
<TextBlock Height="24" HorizontalAlignment="Left" Name="labelText" VerticalAlignment="Top" Width="200" Text="(Value Goes Here)" />
</StackPanel>
<liquidMenu:Menu x:Name="popupMenu" Canvas.Left="40" Canvas.Top="40" ItemSelected="MenuList_ItemSelected" Visibility="Collapsed" Height="Auto" FontSize="8">
<liquidMenu:MenuItem ID="delete" Icon="Images/Delete10.png" Text="Delete" Shortcut="Del" />
<liquidMenu:MenuItem ID="exclusive" Icon="" Text="Exclusive" Shortcut="Ctrl+E" />
<liquidMenu:MenuItem ID="properties" Icon="" Text="Properties" Shortcut="Ctrl+P" />
</liquidMenu:Menu>
</Grid>
Answers to these specific issues are great, a new way to think about this type of issue so that I understand how to control font size is better.

Related

Chinese font renders incorrectly at FontSize less than 22

For the most part, my app renders different character sets without problems. There are, however, certain Chinese characters that render fine when FontSize is 22, but horribly when it is smaller:
This was rendered by the following piece of XAML, which works for both WPF and UWP, with the same problematic results:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBox x:Name="textBox" Grid.Row="0" FontSize="21" Text="〾⿰⿱⿲⿳⿴⿵⿶⿷⿸⿹⿺⿻" />
<TextBox Grid.Row="1" FontSize="22" Text="{Binding Text, ElementName=textBox}" />
<TextBlock Grid.Row="2" FontSize="21" Text="{Binding Text, ElementName=textBox}" />
<TextBlock Grid.Row="3" FontSize="22" Text="{Binding Text, ElementName=textBox}" />
</Grid>
The second and fourth line shows how the string is supposed to look; the first and third show garbled versions.
The answer to this somewhat related question suggests setting FontFamily="SimSun", which does indeed cause things to be displayed correctly. My options, then, currently seem to be:
Change the font family from the default "Segoe UI" to "SimSun"
Increase the font size from 15 to 22
Neither option is appealing. Does anyone have other suggestions? Or an explanation for why those particular characters are so troublesome?
Turns out FontWeight="Light" does the trick:
Medium, Normal and SemiLight all fail. Light, SemiBold, Thin, Bold, ExtraBold, Black, ExtraBlack and ExtraLight all solve the problem.
If anyone knowledgeable about this area has something to contribute, I'm still interested, as I have no idea what causes this behavior.

How to control button layout in Xaml

Im having trouble controlling the exact layout of a button control with XAML.
It seems that whatever i do the button is of a minimum width.
I have a simple button with only a textblock inside the button. But the button has a lot of margin and padding that i cant seem to get rid of (i know of negative margins and padding).
The things i want to know is:
1. Why in the world was it designed this way.
2. what are the groundrules for controlling the exact layout of a button?
My code is as follows:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="80"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0"></StackPanel>
<Pivot Grid.Row="1">
<Pivot.Title>
<StackPanel Orientation="Horizontal" Margin="-15,-3,0,0" Background="red" Width="480">
<Button Background="Blue" x:Name="btnStudies" Click="btnMenuItem_Click" Width="20">
<TextBlock Text="Title" Foreground="White"></TextBlock>
</Button>
<Button Background="Green">
<TextBlock Text="Title" Foreground="White"></TextBlock>
</Button>
<Button Background="Blue" Click="btnMenuItem_Click">
<TextBlock Text="Title" Foreground="White"></TextBlock>
</Button>
<Button Background="Blue" Click="btnMenuItem_Click">
<TextBlock Text="Title" Foreground="White"></TextBlock>
</Button>
<Button Background="Blue" Click="btnMenuItem_Click">
<TextBlock Text="Title" Foreground="White"></TextBlock>
</Button>
</StackPanel>
</Pivot.Title>
</Pivot>
</Grid>
I want five buttons in a row but these are already too wide for the screen (windows phone). Changing the width doesnt seem to have any effect (why is it there).
The textBlock control within the button the button is as wide as the text on it, but i dont seem to have any control on the width of the button. In HTML you only have padding or margin when you define it but in xaml it just seems to be there and for me its unclear how to undo that.
*****EDIT*****
After reading Rachel's reply i decided to start from the ground up.
Using the code below i still have no control over how wide the button is because it uses a certain amount of padding that i cant seem to remove. The button has a width of about 110 when i define a width lower than that it doesnt change. Margins and paddings of 0 have no effect at all (dont want to use negative values just yet because that doesnt seem very intuitive). So the code below is very simple but still the button takes up an amount of space that i dont have any control over. I cant imagine a reason why it was designed this way.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="400" />
</Grid.ColumnDefinitions>
<StackPanel Width="300" Background="Red" HorizontalAlignment="Left">
<Button Background="Blue" HorizontalAlignment="Left" Width="100" Margin="0" Padding="0">
<TextBlock Text="Title" Width="Auto" HorizontalAlignment="Left" />
</Button>
</StackPanel>
</Grid>
The type and size of the parent panel containing the control affects the size/layout of the child controls.
In your case, you have a Grid as your parent panel, and a Grid defaults to taking up all available space. In addition, children placed inside the grid default to taking up all available space as well unless you specify otherwise.
So your <Pivot> is being assigned a width equal to Grid.Width, and Pivot.Title sounds like it's being assigned a width equal to Pivot.Width, and StackPanel is being assigned a width equal to Pivot.Title.Width... you get the picture.
To specify that a control should not take up all available space, specify a HorizontalAlignment or VerticalAlignment property to tell it what side of the parent panel to dock the item on.
For example
<Pivot Grid.Row="1" HorizontalAlignment="Left">
or
<StackPanel OWidth="480" HorizontalAlignment="Left" ...>
If you're new to WPF's layout system, I would recommend reading through the codeproject article WPF Layouts: A Quick Visual Start to quickly learn what the main layout panels are for WPF.

Visual Studio 2010 XAML layout editor not WYSIWYG

When I'm creating WPF layouts in Visual Studio 2010 I just drag and drop controls from the Toolbox onto the default element, typically a Grid. When I do this the spacing shown in Visual studio does not match what's displayed at runtime. For example, here are the visual editor and runtime results, respectively, for two layouts . . .
. . . and . . .
... notice the spacing is altered.
Here's the XAML that was generated for the two examples . . .
<Button Content="ProjectPattern" Height="23" HorizontalAlignment="Left" Margin="12,296,0,0" Name="butProjPattern" VerticalAlignment="Top" Width="117" Click="butProjPattern_Click" />
<TextBlock Height="22" HorizontalAlignment="Left" Margin="135,0,0,141" Name="ResultProjPattern" Text="(result)" VerticalAlignment="Bottom" Width="41" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="175,295,0,0" Name="TextBlockPattern" Text=" (pattern file)" Padding="4" VerticalAlignment="Top" Width="135" Background="#FFF1F3FF" />
<Button Content="...browse" Height="23" HorizontalAlignment="Right" Margin="0,294,814,0" Name="buttonPatternBrowse" VerticalAlignment="Top" Width="54" Click="buttonPatternBrowse_Click" />
...and...
<Button Content="Display Cross" Height="24" HorizontalAlignment="Left" Margin="622,108,0,0" Name="buttonCross" VerticalAlignment="Top" Width="117" Click="buttonCross_Click" />
<TextBlock Height="24" HorizontalAlignment="Right" Margin="0,107,344,0" Name="ResultCross" Text="(result)" VerticalAlignment="Top" Width="100" />
<Button Content="Display Diamond" Height="23" HorizontalAlignment="Left" Margin="622,138,0,0" Name="butDiamond" VerticalAlignment="Top" Width="117" Click="butDiamond_Click" />
<TextBlock Height="23" HorizontalAlignment="Right" Margin="0,138,344,0" Name="ResultDiamond" Text="(result)" VerticalAlignment="Top" Width="100" />
<Button Content="DisplayFullField" Height="24" HorizontalAlignment="Left" Margin="622,165,0,0" Name="butFullField" VerticalAlignment="Top" Width="117" />
<TextBlock Height="24" HorizontalAlignment="Right" Margin="0,164,344,0" Name="ResultFullField" Text="(result)" VerticalAlignment="Top" Width="100" />
I added button handlers, text content, etc, but the layout is strictly what was generated by the Visual Studio layout editor. One thing I noticed is that even though it's drag-and-drop from the Toolbox onto the Grid, Visual Studio is inconsistent about whether it chooses "Left" or "Right" for its HorizontalAlignment for different elements.
The container element is just a default Grid in a default Window - it can minimize but not resize . . .
<Window x:Class="Caller1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="500" Width="1200" ResizeMode="CanMinimize">
<Grid Height="460">
The result is that I have to waste lots of time going between the editor and running my app to "tweak" my layout. What prevents the "WYSIWYG" layout editor from matching the runtime layout and how can I get them to correspond?
Thanks in advance.
I can't see your images (dumb work firewall), but I can tell by your XAML that you are using the Grid wrong. I understand that this may be the fault of the editor, but seriously, you shouldn't be setting the Width and Height properties on all your elements.
If you want a fixed size for the Grid's children, set up some RowDefinitions and ColumnDefinitions and set those sizes. Your layout is much easier to work with (and will probably be more accurate in the designer) if you do this. So, your first Grid would look like this:
<Grid Margin="12,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="117" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="138" /> <!-- This is your desired width + horizontal margins -->
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button x:Name="butProjPattern"
Grid.Column="0"
Content="ProjectPattern"
VerticalAlignment="Center"
Click="butProjPattern_Click" />
<TextBlock x:Name="ResultProjPattern"
Grid.Column="1"
Margin="6,0,0,0"
Text="(result)"
VerticalAlignment="Center" />
<TextBlock x:Name="TextBlockPattern"
Grid.Column="2"
Margin="3,0,0,0"
Padding="4"
Text=" (pattern file)"
Background="#FFF1F3FF" />
<Button x:Name="buttonPatternBrowse"
Grid.Column="3"
Content="...browse"
Margin="22,0,0,0"
VerticalAlignment="Center"
Padding="2,1"
Click="buttonPatternBrowse_Click" />
</Grid>
The other thing I want to note is that after I put this in Kaxaml, which is great for rapid prototyping of your XAML layouts, I noticed that you should really just be using a StackPanel. The first grid could really be this much simpler implementation (you will have to set the Width on a couple of your items to match the layout):
<StackPanel Margin="12,0,0,0" Orientation="Horizontal">
<Button x:Name="butProjPattern"
Content="ProjectPattern"
Width="117"
Click="butProjPattern_Click" />
<TextBlock x:Name="ResultProjPattern"
Margin="6,0,0,0"
Text="(result)"
VerticalAlignment="Center" />
<TextBlock x:Name="TextBlockPattern"
Margin="3,0,0,0"
Padding="4"
Width="135"
Text=" (pattern file)"
Background="#FFF1F3FF" />
<Button x:Name="buttonPatternBrowse"
Content="...browse"
Margin="22,0,0,0"
VerticalAlignment="Center"
Padding="2,1"
Click="buttonPatternBrowse_Click" />
</StackPanel>
This answer is not directly an answer to your actual question, but instead a suggestion to avoid your problem.
You will often get UI control placement problems when you use exact control positioning with the Margin property. It is a good procedure (and in WPF especially) to allow controls to place and/or space themselves using the various Alignment options available. I have always managed to get the desired layout using this method.
For example, had you used a Grid or StackPanel to arrange your controls, you would not have come across this problem. Many WPF developers that I know don't even bother using the designer in Visual Studio because of the problems that you mentioned... after dragging and dropping a control and then going to the XAML to remove unwanted values, it often works out quicker to simply type the XAML myself.
If you really want to know why the Visual Studio designer... well, er... doesn't work properly, you may have more luck asking on the Microsoft Developer Forum, where you question might actually get seen by a Microsoft employee.

Listbox content not dynamically re-sizing when Listbox size changes

I've seen quite a few people asking this question and i feel like my question is slightly different. I have a listbox that holds a series of identical custom made user controls. These controls are added to the listbox at runtime. Now i currently have my listbox items resizing themselves properly upon first creation and insertion into the control.
Here is the strange part. If I resize the listbox the controls that have been visible previously are not resized to the new listbox width. In other words if i add 12 controls and the box only shows 4 (the rest are hidden by a scrollbar) then if i resize the box the first 4 controls will still be the original width and if i scroll then the other 8 will be the correct size. Also if i manipulate the list items in any way they resize themselves to the proper width automatically. SEE EDIT2
I've tried attaching to the sizeChanged event and issuing the following on both the listbox and the items but it has had no effect. I think i need to find some way of resetting the layout information for the listbox items but i can't find the command.
item.InvalidateArrange();
item.InvalidateMeasure();
Layers.UpdateLayout();
item.UpdateLayout();
I think this has something to do with the items i'm adding because even if i detach the items from the lisbox and then attach them they remain the wrong width.
Here is my listbox code:
<ListBox x:Name="Layers" VerticalContentAlignment="Top" Margin="0,17,0,0" BorderThickness="0,1,0,0" HorizontalContentAlignment="Stretch" SizeChanged="Layers_SizeChanged">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Here is the code for my items
<UserControl x:Class="ListOverlayItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:data="clr-namespace:Data"
HorizontalContentAlignment="Stretch">
<UserControl.Resources>
<data:Translator x:Key="translatorString" />
</UserControl.Resources>
<Border BorderBrush="Silver" BorderThickness="0,0,0,0" Name="border1" HorizontalAlignment="Stretch">
<Grid x:Name="layout" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="19"/>
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="60" />
</Grid.ColumnDefinitions>
<!-- Column 0 -->
<ScrollBar Name="arrangeIcon" FlowDirection="LeftToRight" Maximum="10" SmallChange="1" Value="5" Grid.Column="0" Grid.Row="0" Grid.RowSpan="2"/>
<!-- Column 1 -->
<Slider Name="OverlayOpacity" Height="25" Grid.Column="1" Margin="6,0,0,0" Grid.Row="1" Maximum="1" LargeChange="0.1" ValueChanged="OverlayOpacity_ValueChanged"/>
<TextBlock x:Name="OverlayName" Text="{Binding Path=LocationName}" Foreground="#FFF08D2D" Margin="10,2,0,0" Grid.Column="1" FontSize="12" Height="18" VerticalAlignment="Top" />
<!-- Column 3 -->
<Button Name="SettingsButton" Grid.Column="3" Content="{Binding TRK_OV_Settings, Source={StaticResource translatorString}}" VerticalAlignment="Center" Click="SettingsButton_Click" />
<CheckBox x:Name="OverlayEnabled" FlowDirection="LeftToRight" Grid.Column="2" DataContext="{Binding}" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.RowSpan="2" Checked="OverlayEnabled_Checked" Unchecked="OverlayEnabled_Unchecked" />
<TextBlock Name="percentage" Text="100%" FontSize="9" TextAlignment="Right" Grid.Column="2" Grid.Row="1" VerticalAlignment="Center" Margin="2,6,26,6" MinWidth="30"/>
</Grid>
</Border>
Again it seems like my UserControl is correctly able to scale itself its just not getting the command to do so when the parent container is resized.
EDIT: Whoops, removed the WPF tag because it was incorrectly added. I think i've got it down to slider being the culprit. If i set the slider to a fixed size instead of 'stretch' then the item correctly scales just fine. So the question now is how do i force the slider to resize itself.
EDIT2: I know what is causing the issue but i don't know how to solve it. What is happening is the slider that i have in my user control will NOT resize along with the rest of the control unless i change the value of the slider during the resize. The instant i change its value even a fraction it resizes itself automatically. How can i force it to resize?
I determined that the slider was causing the issue and i tried many ways to force the slider to re-draw when it needed to but i was unsuccessful. My final solution was to remove the slider entirely. Works fine now.

WPF/XAML Layout of two Labels containing different length text whilst maintaining equal size Font Scaling

I'm trying position two labels, one right next to the other (with a small amount of spacing).
e.g.
Label 1 Label 2
the content of each label will always be different, most often Label 2 will have more characters but I want the content to scale as the window is resized and I want the font sizes in Label 1 and Label 2 to remain consistent.
I don't care if the contents of Label 2 are cropped if too long.
I've tried using a grid with two columns and placed the Label inside a ViewBox:
<Viewbox Margin="0,0,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
<Label Margin="0,0,0,0" Content="{Binding Path=Suburb}"/>
</Viewbox>
Problem with this is, the positioning is never right and the font sizes don't remain consistent.
What is the best layout method to achieve this? Can I synchronise the font sizes through binding? I've tried binding Label 2's FontSize property to Label 1's FontSize but that doesn't work as it just returns 12 every time no matter how big/small the font really is (I'm presuming the actual FontSize isn't being calculated because the Label is inside a ViewBox).
Any suggestions?
Thanks
You can use the following approach:
<Viewbox VerticalAlignment="Top">
<DockPanel>
<TextBlock Text="Second" DockPanel.Dock="Right" />
<TextBlock Text="First" />
</DockPanel>
</Viewbox>
Note that the second label would never get cropped since the Viewbox would allow the content to render to any size and then scale it. You can specify MaxWidth on the second TextBlock which would limit its size in pixels.
Instead of a DockPanel you can use a Grid with different ColumnDefinitions to achieve the same effect.
The important thing is that they're all in the same Viewbox (which, consequently, doesn't synchronize the FontSize but performs a visual scaling of everything it contains).
The following markup seems to be ok:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Viewbox>
<Label Content="Label 1" Width="{Binding ActualWidth, ElementName=label2}"/>
</Viewbox>
<Viewbox Grid.Column="1">
<Label Name="label2" Content="Label 2 Label 2 Label 2"/>
</Viewbox>
</Grid>
Im not 100% sure of what 'content scale as the window resizes' and 'font sizes remain consistent' actuall means, but I guess you want each label to trim depending on available space.
So why not use TextBlock as below
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Suburb}" TextWrapping="NoWrap" TextTrimming="CharacterEllipsis" Margin="0,0,5,0" />
<TextBlock Text="{Binding Path=Area}" TextWrapping="NoWrap" TextTrimming="CharacterEllipsis" Grid.Column="1"/>
</Grid>
I realize this question is old, but one of the more correct ways to do this is to use Runs.
Runs are sections of text within a TextBlock.
<TextBlock Margin="0,0,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
<Run Text="{Binding Suburb}" />
<Run Text="{Binding Area}" />
</TextBlock>
Keep in mind that everything within a TextBlock is whitespace-sensitive, so if you wanted to have two Runs back-to-back without any space in between, you would do something like this:
<TextBlock Margin="0,0,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
<Run Text="Foo" /><Run Text="bar" />
<!-- Prints 'Foobar' -->
</TextBlock>
It's similar to how HTML is rendered, if there is whitespace between the tags, a single space is rendered on the page between those elements. This rule only applies to items within a TextBlock, not the entire XAML page.

Resources