Clipping rotated objects in WPF - wpf

I want to make a set of buttons with 90 degree rotated text. I created the layout I wanted but found when I attached it to a button the layout clipped according to the button's (unrotated) layout. I haven't been able to figure out what's going on, but I created a simplified case without a button. Here's my XAML:
<Border Height="100" Width="50" BorderThickness="1" BorderBrush="Black">
<TextBlock>This is a test</TextBlock>
</Border>
This produces a border with clipped text (as expected)
But if I rotate the text, resulting in this XAML:
<Border Height="100" Width="50" BorderThickness="1" BorderBrush="Black">
<TextBlock RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="90"/>
<TranslateTransform/>
</TransformGroup>
</TextBlock.RenderTransform>This is a test</TextBlock>
</Border>
the text still clips according to the ''width'' of the enclosing border, not the height.
I'm sure I could size the border to include the text and rotate the border instead, and likely I could do the same with the buttons I'm trying to create, but if I do I don't know that I'm not going to run into the same problem with whatever bounds the buttons, so I feel like I need to understand what I'm missing. Why would a rotated object be clipped as if it wasn't rotated?

Set the LayoutTransform property, instead of RenderTransform:
<Border Height="100" Width="50" BorderThickness="1" BorderBrush="Black">
<TextBlock Text="This is a test">
<TextBlock.LayoutTransform>
<RotateTransform Angle="90"/>
</TextBlock.LayoutTransform>
</TextBlock>
</Border>
If desired, also set HorizontalAlignment="Center" and VerticalAlignment="Center" on the TextBlock.

Related

How to rotate an image inside ScrollViewer? [duplicate]

This question already has answers here:
WPF Clipping Problem
(2 answers)
Closed 5 years ago.
I try to rotate an image in a ScrollViewer (WPF), but the entire image needs to remain visible. The corners of the image are cut off, if rotation angle is for example 45. I tried setting the Width and Height of the image by calculation the surrounding rectangle of the rotated image. It works, but not if the rotation angle is over 45.
<Grid>
<ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Visible" Margin="0,0,0,0">
<Image x:Name="image" RenderTransformOrigin="0.5,0.5" Margin="0,0,0,0" MouseDown="image_MouseDown" MouseRightButtonDown="image_MouseRightButtonDown" MouseLeftButtonDown="image_MouseLeftButtonDown">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="scal"/>
<SkewTransform/>
<RotateTransform Angle="90" x:Name="rot"/>
<TranslateTransform/>
</TransformGroup>
</Image.RenderTransform>
</Image>
</ScrollViewer>
</Grid>
Use a ViewBox in the following structure:
<ScrollViewer Width="100" Height="100" Background="Black" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Viewbox Width="100" Height="100">
<Border Width="100" Height="100" Background="Red" >
<Border.LayoutTransform>
<RotateTransform Angle="30" />
</Border.LayoutTransform>
</Border>
</Viewbox>
</ScrollViewer>
Note that you should set the size of the ViewBox and the inner Control (in your case the Image) equal to the size of the ScrollViewer. The ViewBox will adjust the size of the inner Control, in such a way that the ScrollBars are never Visible.
Note that I used a red Border, you can add the image.
Edit
Just checked it. You do not need to set the Widths, but just the size of inner Control. In other words, this works too:
<ScrollViewer Background="Black" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Viewbox>
<Border Width="1" Height="1" Background="Red" >
<Border.LayoutTransform>
<RotateTransform Angle="30" />
</Border.LayoutTransform>
</Border>
</Viewbox>
</ScrollViewer>

Fit image to page and auto hide scrollbar

<ScrollViewer x:Name="imagescrollviewer" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<!--<Viewbox>-->
<Image x:Name="im" Source="{Binding JpgImageSource}" RenderTransformOrigin="0.5,0.5" Stretch="Uniform">
<Image.RenderTransform>
<ScaleTransform ScaleX="{Binding Value,ElementName=scaleslider}" ScaleY="{Binding Value,ElementName=scaleslider}"/>
</Image.RenderTransform>
</Image>
<!--</Viewbox>-->
</ScrollViewer>
<Slider x:Name="scaleslider" Orientation="Vertical" Height="100" Margin="5" HorizontalAlignment="Center" Maximum="4" Minimum="0.2" Value="1"/>
The scrollbar doesn't adpat to the image size properly. When the image gets bigger, the scrollbar should be shorter and vice versa. Is there some way to figure out the problem?
How to know the slider value when the image is fit to the window?
I suppose you need to use LayoutTransform instead of RenderTransform. This blog post describes the difference very well.
<Image x:Name="im" Source="{Binding JpgImageSource}" >
<Image.LayoutTransform>
<ScaleTransform ScaleX="{Binding Value,ElementName=scaleslider}" ScaleY="{Binding Value,ElementName=scaleslider}"/>
</Image.LayoutTransform>
</Image>

WPF, TextBlock Rotation, Alignment Issues

I would like to rotate the TextBlock based on the text's center point [Horizontal and vertical). I have tried the following code. it is always taking topleft corner of the textblock. How to change it to center of the text itself.
<TextBlock Name="textBlock1" TextWrapping="Wrap" FontSize="25" Foreground="#FFF63AFF" FontWeight="Bold">
TextBlock
<TextBlock.RenderTransform>
<TransformGroup>
<RotateTransform Angle="45" />
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
Image Description: Textblock is part of canvas and textblock should rotate based on the intersection as shown in the image
I have tried HorizontalAlignment as well as VerticalAlignment too, actually it is taking parent's alignment details.
Do I need to get the actual width and actual height, then based on that details calculate the center point?
You need to use RenderTransformOrigin=".5,.5"
<Grid>
<TextBlock Name="textBlock1" RenderTransformOrigin=".5,.5" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap" FontSize="25" Foreground="#FFF63AFF" FontWeight="Bold">
TextBlock
<TextBlock.RenderTransform>
<TransformGroup>
<RotateTransform Angle="45" />
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
</Grid>
Output
add the proprety in textbox :
TextAlignment="Center"
this is for horizontal alignement

Visual brush weird behavior

I have a textbox and a rectangle. The rectangle updates itself when textbox content changes. I'm painting the rectangle fill with visual brush. The problem is that the visual brush don't match the textbox's actual look. What should I do. Here's my code:
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox Name="txtBox"/>
<Rectangle Height="{Binding ElementName=txtBox, Path=ActualHeight}"
Width="{Binding ElementName=txtBox, Path=ActualWidth}">
<Rectangle.Fill>
<VisualBrush Visual="{Binding ElementName=txtBox}"/>
<Rectangle.Fill>
<Rectangle.LayoutTransform>
<ScaleTransform ScaleY="-0.75"/>
</Rectangle.LayoutTransform>
</Rectangle>
</StackPanel>
Here I wrote "Visual Brush",
then deleted few chars and look what I got:
Made a small change to your Xaml based on the information in your comment. The problem seems to be that the TextBlock doesn't have a Background so I guess that the VisualBrush just finds the visible part of the TextBlock for rendering and then stretches it to the full length of the TextBlock based on the Bindings.
The following Xaml works fine when the TextBlock has Background="Transparent" but reproduces your problem without it
Update: In the chat, the OP found that the Width Binding kept the TextBox from shrinking when deleting characters. So removing the Width binding fixes the centering issue as well.
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox Name="txtBox"/>
<TextBlock Name="textBlock" Text="{Binding ElementName=txtBox, Path=Text}"
Background="Transparent"/>
<Rectangle Height="{Binding ElementName=textBlock, Path=ActualHeight}">
<Rectangle.Fill>
<VisualBrush Visual="{Binding ElementName=textBlock}"/>
</Rectangle.Fill>
<Rectangle.LayoutTransform>
<ScaleTransform ScaleY="5"/>
</Rectangle.LayoutTransform>
</Rectangle>
</StackPanel>

WPF - drawing text onto a GridSplitter

I am declaring this Grid Splitter:
<GridSplitter HorizontalAlignment="Right" VerticalAlignment="Stretch" Grid.Column="1" Grid.RowSpan="1" Grid.Row="1" Width="5" Background="#FFBCBCBC" ResizeBehavior="PreviousAndNext">
</GridSplitter>
It is a vertical grid splitter and I want to draw some text using RotateTransform so the text runs from top to bottom. I am having trouble getting it to work.
This should render the text as rotated.
<TextBlock Text="Testing" HorizontalAlignment="Center" VerticalAlignment="Center" IsHitTestVisible="False">
<TextBlock.LayoutTransform>
<RotateTransform Angle="90" />
</TextBlock.LayoutTransform>
</TextBlock>
You would then need to include it after your GridSplitter in the same column. The IsHitTestVisible is just in case it interferes with the mouse.
EDIT: Just to be clear, this would be a child of the Grid, not the GridSplitter. It would simply render on top of the GridSplitter.

Resources