WPF - drawing text onto a GridSplitter - wpf

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.

Related

Clipping rotated objects in 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.

WPF Scaling an Image inside a Canvas

When I place the following code in a Window or UserControl, the image is displayed with its native width and height. Is there a way to automatically scale outer canvas to proportions of the containing window while retaining the proper aspect ratio for the window?
<Canvas Background="AliceBlue">
<Canvas.LayoutTransform>
<ScaleTransform ScaleX="1" ScaleY="1"/>
</Canvas.LayoutTransform>
<Image Source="ImageName.jpg" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Canvas Canvas.Top="20" Canvas.Left="20" Width="20" Height="20" Background="Salmon"/>
</Canvas>
A Canvas never resizes its child elements. Put the Image control in a Grid instead, then probably put the whole thing in a Viewbox:
<Viewbox>
<Grid>
<Image Stretch="None" Source="ImageName.jpg" .../>
<Canvas Margin="20,20,0,0" Width="20" Height="20" Background="Salmon"/>
</Grid>
</Viewbox>
Wrap your Canvas in a ViewBox.

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

Stretch items to fill canvas

I have a Dockpanel with items inside a Canvas. The Dockpanel and any other items (Grid etc) that I place inside the Canvas, only take up their minimum required space. How do I stretch these items to fill the entire Canvas?
<Canvas x:Name="InfoCanvas" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="72,53,0,0">
<DockPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="0,0,0,0" x:Name="ReferenceInfo" Canvas.Left="0" Canvas.Top="0">
<TextBox x:Name="ReferenceAuthor" GotFocus="FieldEnter" LostFocus="FieldLeave" FontSize="16" FontFamily="Segoe UI Light" Text="Author" Foreground="Gray" Background="Transparent" DockPanel.Dock="Top" VerticalAlignment="Top" HorizontalAlignment="Stretch" BorderThickness="0" Margin="0,2,0,2"/>
<TextBox x:Name="ReferenceTitle" GotFocus="FieldEnter" LostFocus="FieldLeave" FontSize="16" FontFamily="Segoe UI Light" Text="Title" Foreground="Gray" Background="Transparent" DockPanel.Dock="Top" VerticalAlignment="Top" HorizontalAlignment="Stretch" BorderThickness="0" Margin="0,2,0,2"/>
<TextBox x:Name="ReferenceDate" GotFocus="FieldEnter" LostFocus="FieldLeave" FontSize="16" FontFamily="Segoe UI Light" Text="Date" Foreground="Gray" Background="Transparent" DockPanel.Dock="Top" VerticalAlignment="Top" HorizontalAlignment="Stretch" BorderThickness="0" Margin="0,2,0,2"/>
</DockPanel>
</Canvas>
Thank you!
The Canvas panel doesn't really support that.
It's very basic - it just allows you to position children absolutely by using Top, Bottom, Left and Right, and it always gives them just the space they need.
So usually you would use a Grid with just 1 column and 1 row instead.
You can however bind the width and height of the DockPanel to the width and height of the Canvas. That way the DockPanel will always fill the Canvas.
<DockPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Margin="0,0,0,0" x:Name="ReferenceInfo" Canvas.Left="0" Canvas.Top="0"
Width="{Binding ActualWidth, ElementName=InfoCanvas}"
Height="{Binding ActualHeight, ElementName=InfoCanvas}">
What you can do is:
<Grid>
<Canvas x:Name="InfoCanvas">
<!--Elements with canvas layout here-->
</Canvas>
<DockPanel x:Name="ReferenceInfo">
<!--Elements with dockpanel layout here-->
</DockPanel>
</Grid>
By wrapping both panels in a grid like this you can place elements that you cant to position relative to left, top etc in the canvas. Both the canvas and the dockpanel will fill available space. Note that the elements in the dockpanel will be rendered above the elements in the canvas when the dockpanel is defined after in xaml.
I'm assuming the code you posted is pseudo code, if not you should just remove the canvas.

Binding to ActualHeight does not work

I tried to create a custom control, having a semitransparent rounded background:
<Canvas>
<TextBlock x:Name="StopText" Text="Some test text"/>
<Rectangle Fill="SkyBlue"
Width="{Binding Source=StopText, Path=ActualHeight}"
Height="20"
RadiusX="5" RadiusY="5" Opacity="0.2"/>
</Canvas>
The problem is that I can't, probably, bind to the ActualHeight/ActualWidth properties, cause they are not dependency ones.
What to do to mantain the rectangle and textbox of same size?
The correct binding is to use ElementName, not Source, when binding to another element:
<Canvas>
<TextBlock x:Name="StopText" Text="Some test text"/>
<Rectangle Fill="SkyBlue"
Width="{Binding ElementName=StopText, Path=ActualHeight}"
Height="20"
RadiusX="5" RadiusY="5" Opacity="0.2"/>
</Canvas>
Also, you do realize that you are binding the width of the Rectangle to the Height of the TextBlock, right?
If this is really the way you want to set up your control, you will want to bind the Rectangle's Width to the TextBlock's ActualWidth, and Height to ActualHeight.
UPDATE
Per the comments below, here is an implementation using a Grid with no binding:
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock x:Name="StopText" Text="Some test text"/>
<Rectangle Fill="SkyBlue"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
RadiusX="5" RadiusY="5" Opacity="0.2"/>
</Grid>
Grid and Canvas use different layout systems, and since you aren't using the functionality the Canvas provides, Grid is the better choice.
The big difference in the child elements is that the Rectangle now just uses Horizontal and VerticalAlignment to Stretch across the entire Grid, instead of worrying about the sizes of anything.

Resources