How to fit TextBlock size to text size - silverlight

i am working in silverlight for embedded windows and i want to fit text to the TextBlock as seen on picture, i want textBlock to fit text ( i want to remove yelow space in attached picture )
Can someone help me with this?
Best regards,
Luka
Here is the XAML i am currently using:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="FullTest.PUIsocUI"
d:DesignWidth="480" d:DesignHeight="272">
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" Height="64" Grid.Row="1">
<RadioButton x:Name="PowerMeasurement" GroupName="PowerTabControls" IsChecked="True" Checked="PowerMeasurement_Checked" Unchecked="PowerMeasurement_Unchecked" Content="POWER" BorderThickness="0"/>
<RadioButton x:Name="PowerMode" GroupName="PowerTabControls" Checked="PowerMode_Checked" Unchecked="PowerMode_Unchecked"/>
<RadioButton x:Name="PowerLimit" GroupName="PowerTabControls" IsChecked="False" Click="PowerLimit_Click" Checked="PowerLimit_Checked" Unchecked="PowerLimit_Unchecked"/>
</StackPanel>
<Grid>
<Grid x:Name="PowerMeasurementPage" Margin="0,0,0,64" >
<!-- tab page za meritev-->
<TextBlock Text="POWER" Style="{StaticResource FunctionNameTextBlockStyle}" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<TextBlock Text="11.555" Style="{StaticResource ResultNameTextBlockStyle}" />
</Grid>
<Grid x:Name="PowerModePage" Margin="0,0,0,64">
<!-- tab page za Mode-->
</Grid>
<Grid x:Name="PowerLimitPage" Margin="0,0,0,64">
<!-- tab page za Limita-->
</Grid>
</Grid>
</Grid>
<Style TargetType="TextBlock" x:Key="FunctionNameTextBlockStyle">
<Setter Property="FontFamily" Value="ALTERNATE_GOTHIC#AlternateGothic2 BT"/>
<Setter Property="FontSize" Value="44"/>
<Setter Property="Margin" Value="57,27,0,0"/>
</Style>
this is what i want to get ->

<TextBlock Text="POWER" FontSize="44" FontWeight="SemiBold" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<CompositeTransform ScaleY="2"/>
</TextBlock.RenderTransform>
</TextBlock>
In the example I've provided see the ScaleY declaration? Adjust that value to meet your needs. That's one way to accomplish that effect without using ViewBox. Another might be to convert that TextBlock in to a Path and adjust as necessary also, but it would have to be a static label for that to be useful.
Hope this helps! :)

The other way is even much simpler. You just have to let TextBlock to resize itself, it will arrange itself based on text. You should look into its container probably (probably paste some code?). Try setting TextBlock like this:
<TextBlock Text="POWER" HorizontalAlignment="Center" VerticalAlignment="Center" />
UPDATE look into VS, to me it seems that it is just a font reserved space. Not sure how you can avoid that.

In VS2015 you can do this easily with TextLineBounds property (set it to Tight in your case). I use it in UAP, not sure it's available in Silverlight. However it gets truncated for lowercase letters like g, q, etc as posted here: TextLineBounds snipping bottom of letters

Related

How To Make A WPF UserControl Act As A Container

I'm trying to create a Toolbar control that can group selected buttons with a border and a label. If there is already a built-in control that will do this then I could use that instead of building a UserControl.
If not, then what I'm wanting to build is a UserControl that would allow me to enter one-to-many of my ImageButton UserControls and set a GroupLabel text like below. Can this be done in WPF?
<User_Controls:ToolbarGroup GroupLabel="Entity">
<User_Controls:ImageButton ButtonText="Entity Setup"/>
<User_Controls:ImageButton ButtonText="New Entity"/>
</User_Controls:ToolbarGroup>
PS: I would post an image but this quirky forum won't allow me to post an image.
If i have got you correctly then I think you can achieve this way also, and on mouse eneter and leave event you can do the button click job.
for setting text you can use a grid and a label inside it to set the text, and Image buttons below it.
<UserControl x:Class="ABC.View.Oats"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Image Source="{Binding Image}" Stretch="Fill"/>
</Grid>
</UserControl>
I think what you're looking for is a GroupBox, it has a header property where you can set the label.
Something like this:
<GroupBox Width="300" Height="100">
<GroupBox.Header>
<Label>Text</Label>
</GroupBox.Header>
<StackPanel>
<Button Content="Button"/>
<Button Content="Button"/>
<Button Content="Button"/>
</StackPanel>
</GroupBox>
I would also recommend using the groupbox, it seems to be doing exactly what you want it to do and it looks neat. Here's some examples on how to use them: http://www.dotnetperls.com/groupbox-wpf
On the other hand, if you believe the groupbox is not sufficient, you could create a control that inherits from the groupbox and you could extend it and add whatever you need to it. It would look like this:
public class customGroupBox: GroupBox{
....Add whatever you need here
}
Thanks for the replies. I tried the GroupBox and it's not the layout we want because we want the label underneath the buttons and centered. I never could find a way to add a collection to the UserControl. Maybe I didn't ask the question right by calling it a container. The code below will work, but it's not elegant. I wanted something that would wrap the layout in a UserControl and allow me to add a variable number of buttons to each toolbar group.
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0">
<Border Background="GhostWhite" BorderBrush="Gainsboro" BorderThickness="1">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<User_Controls:ImageButton ButtonText="New 1"/>
<User_Controls:ImageButton ButtonText="New 2"/>
<User_Controls:ImageButton ButtonText="New 3"/>
</StackPanel>
<Label HorizontalAlignment="Center" Content="Group 1"/>
</StackPanel>
</Border>
<Border Background="GhostWhite" BorderBrush="Gainsboro" BorderThickness="1">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<User_Controls:ImageButton ButtonText="New 4"/>
</StackPanel>
<Label HorizontalAlignment="Center" Content="Group 2"/>
</StackPanel>
</Border>
</StackPanel>
One way to accomplish this is with a custom styled ItemsControl.
You can then reuse it and just bind it to different data.
Please forgive me, this is hand-typed...
In your resources...
<Style x:Key="ToolbarGroupItemsControlStyle" TargetType="ItemsControl">
...
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ItemsControl">
<Grid>
... XAML to form your group with a binding to the
... group name
<ItemsPresenter/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="ToolbarGroupItemTemplate">
<Grid>
... XAML and binding for each toolbar group item ...
</Grid>
</DataTemplate>
In your XAML...
<ItemsControl
Style="{DynamicResource ToolbarGroupItemsControlStyle}"
ItemsSource="{Binding ToolbarGroupItems}"
ItemTemplate="{DynamicResource ToolbarGroupItemTemplate"/>
If your resources above are at the application level, then you can place the ItemsControl above on any Window/UserControl you want.
Your ItemsSource will need to be a collection of a custom type you create that has bindings for the button text, etc.
I hope this is helpful.

wfp charting toolkit: show data point values above all columns

total emergency here. Just saw WPF for the first time and need this quick, so forgive me: if I don't provide enough info first time around I promise to edit the question.
In a charting object, defined with namespace:
xmlns:charting="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
I am drawing a simple bar chart.
<charting:Chart Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3"
Visibility="{Binding Path=MyCurrentResultsView, Converter={StaticResource ResourceKey=NullObjectToVisibilityConverter}}"
Background="Transparent" Foreground="White"
Margin="50,0,50,0" Height="350"
HorizontalAlignment="Stretch" Title="{Binding Path=MyCurrentResultsView.Name}">
<charting:ColumnSeries Height="350" Foreground="Black"
ItemsSource="{Binding Path=MyCurrentResultsView.ResultsView}"
IndependentValueBinding="{Binding Key}"
DependentValueBinding="{Binding Value}">
</charting:ColumnSeries>
</charting:Chart>
What I'd like to do is to show the value of each column above the column (or even inside the column rectangle if possible: these are percentage values and the idea is to make them more visible on the bar chart).
I have been looking at the styling information, but here this is more than just style. I see two possibilities. Either:
For each column item in the series, define a transformation that positions a frame above each column, creates a text box whose label is set to the dependent value, then draws the text box inside the frame.
Find some kind of property on "ColumnSeries" or "? ColumnItem ?" that "enables" the display of the bound value above the column.
Total shot in the dark here. Thanks.
I would try to change the ColumnDatapointTemplate like this:
<charting:ColumnSeries Height="350" Foreground="Black"
ItemsSource="{Binding Path=MyCurrentResultsView.ResultsView}"
IndependentValueBinding="{Binding Key}"
DependentValueBinding="{Binding Value}">
<charting:ColumnSeries.DataPointStyle>
<Style TargetType="charting:ColumnDataPoint">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="charting:ColumnDataPoint">
<Grid>
<Rectangle Fill="{TemplateBinding Background}" Stroke="Black"/>
<Grid Margin="0 -20 0 0" HorizontalAlignment="Center" VerticalAlignment="Top">
<TextBlock Text="{TemplateBinding FormattedDependentValue}" Margin="2"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</charting:ColumnSeries.DataPointStyle>
</charting:ColumnSeries>
Play a bit with vertical alignments and/or margins and you will be able to get infos into the columns and other.
Hope this help!

WPF IDataErrorInfo issues

I've used WPF and IDataErrorInfo in the past apps to display errors to the user via a controltemplate by putting an image in the adorner and adding a tooltip to the image like this;
<Style x:Key="textStyle" TargetType="TextBox">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<Border BorderBrush="Orange"
BorderThickness="2"
CornerRadius="4"
SnapsToDevicePixels="True">
<Border.Effect>
<DropShadowEffect BlurRadius="10"
ShadowDepth="0"
Color="Orange" />
</Border.Effect>
<DockPanel>
<Image Width="16"
Height="16"
Margin="-20,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
RenderOptions.BitmapScalingMode="HighQuality"
Source="{StaticResource imgError}"
ToolTip="{Binding ElementName=adornedElement,
Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}"
ToolTipService.ShowDuration="30000" />
<AdornedElementPlaceholder Name="adornedElement" />
</DockPanel>
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
With the appropriate implementation of IDataErrorInfo in the ViewModel and setting Textbox in the view accordingly the image and tooltip are shown;
<TextBox Name="txt"
Grid.Column="0"
Height="40"
Background="Aqua"
Style="{StaticResource textStyle}"
Text="{Binding Path=Text,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True}" />
<TextBlock Grid.Column="1"
Height="40"
Background="AliceBlue"
Text="{Binding ElementName=txt,
Path=(Validation.Errors).CurrentItem.ErrorContent}" />
The above code displays correctly in my previous apps and shows the error in the image tooltip as confirmed by the Textblock.
However, in my current app which is built using Prism I can't get the Image to display. The TextBlock updates correctly and I can set the error to the TextBox tooltip via a style trigger without any issue. The problem is I can't seem to get the image (or anything else) to display in the Adorner. The Image is not shown and border is not changed.
The difference between previous apps and this is that the view is in a Region in a ContentControl and I've used dependency injection to inject the viewmodel into the view constructor and set the DataContext.
I can't figure out why this doesn't work when it did previously. I think I may need to include an AdornerDecorator somewhere but I'm perplexed as to where having tried it in a few places without success. Any ideas how I can ensure the Adorner is shown?
Used an AdornerDecorator to wrap the element containing the texbox and all works fine.

Border control expands to size of Grid instead of just surrounding an Image control

I wanted a <Border> around my <Image> - sounds simple enough. but I could never get it to appear. I eventually made it "Red" with "BorderThickness=20" - then it was obvious that it was going around the entire "LayoutRoot"! Something like:
<UserControl x:Class="BorderCrossing.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Margin="10" Background="Black">
<Border Canvas.ZIndex="1" Background="White" HorizontalAlignment="Center" Opacity=".5" VerticalAlignment="Top">
<TextBlock x:Name="idTextBlock" FontSize="20" FontWeight="Bold" Foreground="Black" Text="ID Here" />
</Border>
<Border Canvas.ZIndex="1" Background="Blue" BorderThickness="5" BorderBrush="AntiqueWhite">
<Image x:Name="thumbnailImage" Height="100" Width="100" Stretch="Uniform" />
</Border>
</Grid>
In order to "fix" this, I found that adding 'HorizontalAlignment="Left" VerticalAlignment="Top"' to the <Border> placed the border around the <Image>, as desired. I also found that I could enclose the <Border> in a <Canvas> and achieve a similar result.
What is going on? Can someone explain this in a way that will prevent my "wonder" in the future?
Thanks,
David
The default for VerticalAlignment and HorizontalAlignment is "Stretch", so the Border stretches to the entire available space by default. It does not happen inside of a Canvas because a Canvas does not take these properties into account when performing layout of its children, so they get the minimum size based on properties like Width, Height, MinWidth and similar properties of their children. Positioning in a Canvas is done with Canvas.Top and Canvas.Left properties, while a Grid uses the ~Alignment properties as well as Margins.

Keeping Canvas overflow in WPF

I have a (hopefully) interesting question.
First of all what I'm trying to do here:
I'm trying to create a pie-chart-like set of buttons, later this control will be used within a touch enabled application. The control draws and looks just fine, also all of the behaviours are fine so far. However, one thing that I'm having issues with is the translations I do to all the pieces of the pie.
SO what I do is: I want margin n between the pie pieces, to create this margine I move all pieces away from the middle. This means that the pie piece that's facing UP will have a negative translation. This in turn means that the Canvas will clip a part of the top (due the top being at 14, -2 for example). Another thing that I've added are pieces of text which are also making the pie pieces quite a bit longer. See the image included for reference.
image
To the left you can see the clipping issue I'm talking about to the right you can see an arbitrarily translated version of the same thing.
Some code paste:
Main window XAML:
<controls:PieMenu Radius="100" Padding="10">
<controls:PieMenu.MenuItems>
<controls:PieMenuItem Text="Employment" Brush="#FF33FF" Command="BrowseBack" />
<controls:PieMenuItem Text="General" Brush="#9933FF" Command="BrowseBack" />
<controls:PieMenuItem Text="Internships" Brush="#3333FF" Command="BrowseBack" />
<controls:PieMenuItem Text="Bla" Brush="#3399FF" Command="BrowseBack" />
<controls:PieMenuItem Text="Bla" Brush="#007AF5" Command="BrowseBack" />
</controls:PieMenu.MenuItems>
PieMenu XAML:
<UserControl x:Class="PieControlLibrary.PieMenu"
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:self="clr-namespace:PieControlLibrary"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<!-- <CollectionViewSource x:Name="menuItemCollectionViewSource" Source="{Binding MenuItems, RelativeSource={RelativeSource AncestorType=self:PieMenu}}"/>-->
<Style TargetType="{x:Type ListView}" x:Key="listViewStyle">
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<self:PieButton Radius="{Binding Radius, RelativeSource={RelativeSource AncestorType=self:PieMenu}}"
Degrees="{Binding Degrees, RelativeSource={RelativeSource AncestorType=self:PieMenu}}"
Brush="{Binding Brush}"
Command="{Binding Command}"
Text="{Binding Text}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<ListView x:Name="menuItemsView" ItemsSource="{Binding MenuItems, RelativeSource={RelativeSource AncestorType=self:PieMenu}}" Style="{StaticResource listViewStyle}" />
</Grid>
PieButton (this is what the pie menu items are converted to)
<UserControl x:Class="PieControlLibrary.PieButton"
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:control="clr-namespace:PieControlLibrary"
xmlns:TextOnPath="clr-namespace:Petzold.TextOnPath"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
>
<Grid>
<Button HorizontalAlignment="Left" VerticalAlignment="Top" DataContext="{Binding RelativeSource={RelativeSource AncestorType=control:PieButton}}" Command="{Binding Command}">
<Button.Template>
<ControlTemplate>
<Canvas >
<Path Data="{Binding PathData}" Fill="{Binding Brush}" Grid.Row="0" Grid.Column="0" />
<TextOnPath:TextOnPathControl PathFigure="{Binding TextPath}" Text="{Binding Text}" FontFamily="Consolas" FontSize="12" Foreground="Black" FontStretch="Normal" />
</Canvas>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
I'm not sure if I understand your question, but when you draw your pie chart, just leave some extra space around the edges so you can move the pie pieces out from the center?
Perhaps you could use a RenderTransform when your pie pieces expand to shift or scale the image a tiny bit to keep it in bounds?

Resources