WPF: how to write text in a different direction? - wpf

I need to write text in the orientation specified for the image below. The fact is that I saw some examples around here by using a textblock and rotating the angle of the control using "RenderTransform", but this is not what I really need. I tried to do it using an image but it doesn't fit very well... so I really don't know how to solve it. If you look at the image beside you can see that the text is written from bottom to top and the line below the text is in the right of the screen.
This is the screen that I need to develop:
I tried by rotating the textblock, but the only way that it works for me was wrapping the text, but this is just the "closest" solution that I found. Also, as you can see, I need to set a border for the textblock.
Anyway, I hope you can help me because any example around fits with my problem.

In order to rotate your text at 90 degrees, I believe that you will need to use the LayoutTransform instead of the RenderTransform:
<TextBlock Text="FootRoller" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"/>
</TextBlock.LayoutTransform>
</TextBlock>
The difference is when the transform will be applied. Using the LayoutTransform, the text will be rotated before the layout pass and this will be important in your case. I imagine that using the RenderTransform will rotate your TextBlock, but as it does that after the layout pass, it would not show it all... this is because it was measured for size before it was rotated.
You can find out full details from the Transforms Overview page on MSDN. From the linked page:
LayoutTransform – A transform that is applied before the layout pass. After the transform is applied, the layout system processes the transformed size and position of the element.
RenderTransform – A transform that modifies the appearance of the element but is applied after the layout pass is complete. By using the RenderTransform property instead of the LayoutTransform property, you can obtain performance benefits.

They're all right. RenderTransform should be all you need. Like;
<TextBlock Text="FootRoller" RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.RenderTransform>
<CompositeTransform Rotation="-90"/>
</TextBlock.RenderTransform>
</TextBlock>
P.S. - You can literally just change RenderTransform to LayoutTransform which Sheridan has provided an explanation for in his answer.

If RenderTransform didn't work, take a look at LayoutTransform. You didn't tell us why RenderTransform didn't work but it's usually a safe bet that LayoutTransform will solve whatever problem it gave you.

Related

Trying to wrap and scale text in a textblock WPF

I'm trying to auto scale the font and wrap text in a TextBlock in WPF and I can't figure it out.
I've Googled it and looked at stackoverflow loads of times and the main suggestion is to place a TextBlock inside a ViewBox. I've tried that, and all it does is scale the whole text down to one line instead of wrapping it.
If I just use a TextBlock without a ViewBox it wraps, but doesn't scale to fit. It's driving me mad, as I am literally trying to move from WinForms to WPF to make better looking UIs.
I've tried StackPanel and DockPanel and they still don't have the desired effect.
All I want is a TextBlock to take a string of text of unknown size and display it scaled and wrapped. I don't understand why it's so difficult
It is helpful to include code of what you have tried.
When I do this:
<Grid>
<TextBox VerticalAlignment="Center" TextWrapping="Wrap" Width="100"/>
</Grid>
I get this:
Is that what you are looking for?
You could also check out the RichTextBox if you need more features.

WPF control origin point

After some investigation, I still can't find method to change origin of control.
So, I want just to place one square exactly in center of another square, without margins, so it will be completely independent of first square size.
Theoretically, it can be easily done with HorizontalAlignment and VerticalAlignment set to Center, since it automatically sets Margin of control to half of width and height of parent control. But it is not so simple.
Simplest way to describe problem is next picture
As you can see, margin is counted towards upper left corner. Which is what I call origin. The perfect solution is to change it to center of first square, but this is where I need help - how can I do that?
Point of origin applies when using a transform object, and attaching the transform to your control. It won't actually effect the behaviour of the margin or left, top properties. If using a transform to place your object, point of origin is very useful.
The top, left (if using cavas) and margin (if using say grid) help govern the "auto" placement by the parent control, and this in turn governs where point of origin for the control winds up being relative to the parent control. The transform object then offsets RELATIVE to where that point of origin is.
The other useful thing is that transform overrides the auto placement in the parent control, or rather, forces an offset to where the parent wants to put it, which in some cases is useful - i.e., you might have boxes listed in a grid and want them to "shake" left and right when you hover the mouse over them, their alignment stays in order to the grid, but the transform lets you bump them away from their "forced" position.
For example, attach the same transform object to 2 controls, and set their origins separate, then apply an animation to the transform object - both controls will animate off the one animation object (if you wanted to their movement in perfect sync).
Well, it was weird enough. The given behaviour can be seen only when using Image, and Center alignment. Can be solved by either wrapping Image in Grid, which will be using Center alignment, or using Stretch alignment with Image (which is much simplier).
<Grid Width="500" Height="500">
<Image Width="250" Height="250" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
</Grid>
If you want to reproduce problem I've described in question, replace Stretch with Center in code above.
Probably oversimplifying here but I would just use a Grid to wrap the two items you mentioned like this example (One stretched to fit and one centered):
<Grid>
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderBrush="Black" BorderThickness="10" Margin="4"/>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Padding="10">InnerButton</Button>
</Grid>

Rotate the text inside a small grid/panel

<Label Grid.Row="1"
Height="70"
Margin="2"
Width="300"
Content="{l:Translate Key={x:Static l:MultistringTags.SHOW_MENU}}"
DockPanel.Dock="Bottom"
FontSize="20"
FontWeight="Bold"
Foreground="White">
<Label.RenderTransform>
<RotateTransform Angle="270" />
</Label.RenderTransform>
</Label>
Here I want to rotate the text, which is inside a grid and a grid column width equals with text height. In this case I see only part of text like if text was drawn without rotating cutted of by grid width, and rotated to required angle. I have tried panels, they give me same result.
Does anybody know some workaround to make it show all the text and I don't want to use image because text should be translatable.
I believe if you change it to set the LayoutTransform instead of RenderTransform, it will prevent the text from being cut off.
<Label.LayoutTransform>
<RotateTransform Angle="270" />
</Label.LayoutTransform>
Further to #nekizalb's answer stating that you should use a LayoutTransform, the reason that you would need to do that instead of using a RenderTransform is because of the timing at which each occurs... a LayoutTransform will affect results of layout.
From the UIElement.RenderTransform Property page on MSDN:
A render transform does not regenerate layout size or render size information. Render transforms are typically intended for animating or applying a temporary effect to an element. For example, the element might zoom when focused or moused over, or might jitter on load to draw the eye to that part of the user interface (UI).
From the FrameworkElement.LayoutTransform Property page on MSDN:
In contrast to RenderTransform, LayoutTransform will affect results of layout.
Example scenarios where LayoutTransform would be useful include: rotating elements such as menu components from horizontal to vertical or vice versa, scaling elements (zooming in) on focus, providing editing behavior, etc.

How can I create an opacity mask in wpf that doesn't scale?

Ok, I've created a PNG-24 with transparency. It's basically a grayscale image that uses 'colors' in between black and transparent instead of black and white. I did this so I can use this as the Opacity Mask of a colored rectangle, thus rendering the image in whatever color I want using only a single graphic.
However, for the life of me, I can't get WPF to stop anti-aliasing the da*n image!!
I've set 'SnapesToDevicePixels' on the rectangle to which the brush is applied... I've set the ImageBrush's Scale to 'None'... I've set its ViewPort and the ViewBox to absolute units and sized them exactly to the source image. But no matter what I try, WPF still insists on trying to smooth things out! This is VERY frustrating!!!
So... anyone know how to use an image as an opacity mask but not lose the pixel-precise drawing that we have done? I just want WPF to render the damn thing as we drew it, period!
I have tried to reproduce your problem. Simply like this:
<Rectangle Width="200" Height="200" Fill="Red">
<Rectangle.OpacityMask>
<ImageBrush ImageSource="/mask.png"/>
</Rectangle.OpacityMask>
</Rectangle>
mask.png contains a simple diagonal mask, like that half of rectange is visible and other half is 100% transparent.
And recrangle is rendering pixel perfect (and aliased, as you want).
I think, that you may a DPI setting, that is not native to your monitor, and WPF just can`t render images correctly.
GOT IT! It's a layout issue that for some reason, there's no easy way to change. However, there's a value you can set called UseLayoutRounding that fixes it. I just set it at the root level (for this fauxample, a grid...)
<Grid UseLayoutRounding="True">
....
</Grid>
...and BAM! Works like a charm! "Sort of" like a 'SnapsToDevicePixels' but for positioning of elements (i.e. it rounds all layout-related values like left, width, etc. whereas SnapsToDevicePixels snaps the layout to the on-screen pixels when rendering.)
M

Silverlight Border - Am I stupid?

sorry, I did not find something useful when searching google. Very basic question, mainly "Am I stupid". I know StackPanel gives its child elements full space, but why does the "Auto" property relate to the PARENT element in case of a border. I mean perhaps I am doing something wrong, but this behaviour is definitly not what I intended:
Pic1 http://img6.imageshack.us/img6/171/20090805002723.jpg
Ok, after some thinking I found a way, which looks like this:
Seriously http://img18.imageshack.us/img18/3173/20090805003045.jpg
But really, this way? I mean a "minimal sized control" with a textbox (which width I want to define) and a border around it, and I need this kind of tree? If anyone has a better way, please tell me...
Chris
PS: And that while I am writing about the nice UI composition for Silverlight, and wanted to give a simple example.. I just say: Legendary!
Definitely not stupid. This can be very confusing. I find it helps when thinking about layout in WPF/Silverlight to think top down from the root of the control hierarchy instead of bottom up.
It becomes obvious when you think about the stack panel's job. It stacks up its child elements and sets their widths to its width. It is therefore overriding your border's width of Auto. The Canvas you later wrapped around it does not try to rearrange its children at all, and it does not override their widths, so while its width is the width of the stack panel, the Auto on your border is now working (sized to its content, the TextBox).
Clear as mud?
Here is an article with more detail:
http://msdn.microsoft.com/en-us/library/ms745058.aspx
And I highly recommend the WPF book by Chris Sells & Ian Griffiths to get up to speed on the intricacies of WPF/Silverlight layout.
Canvas sould be avoided unless it really makes sense for what you're trying to do. For example, Canvas normally makes sense for a game, or something where you want to drag elements around. Here it's just getting in your way.
Reasons not to use Canvas:
http://blogs.msdn.com/devdave/archive/2008/05/21/why-i-don-t-like-canvas.aspx
An easy way is to get rid of the Stackpanel and just use the VerticalAlignment and HorizontalAlignment to keep it at the top left. Then just set the Border Width and leave the Height alone.
<Grid x:Name="LayoutRoot">
<Border Width="150" BorderBrush="Blue" BorderThickness="1" VerticalAlignment="Top" HorizontalAlignment="Left">
<TextBox Text="I'm Serious" Background="LightBlue" />
</Border>
</Grid>

Resources