Bind rotation of content to the rotation of ancestor - wpf

I want to create a control with customized content.
The text inside should be rotated in the opposite direction to always be displayed vertically. To do this I have to bind rotation angle of text to rotation angle of text ancestor. How to do it? Sorry for my English.

Something like this should work. The important thing is to invert the rotation direction by two mirror transforms, before and after the child element rotation.
<Grid Background="AliceBlue" Width="200" Height="200"
RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<RotateTransform Angle="45"/>
</Grid.RenderTransform>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
Text="Hello" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="-1"/>
<RotateTransform Angle="{Binding RenderTransform.Angle,
RelativeSource={RelativeSource AncestorType=Panel}}"/>
<ScaleTransform ScaleX="-1"/>
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
</Grid>

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.

How to add a border rectangle around image control in wpf?

I tried to add the wrapped the <Image with <border
I added
<Border BorderThickness="1">
And
</Border>
Then tried to wrapped the <Image like this :
<Border BorderThickness="1">
<Image x:Name="Img" HorizontalAlignment="Left" Height="233" Margin="467,54,0,0" VerticalAlignment="Top" Width="272" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform AngleY="0.704"/>
<RotateTransform/>
<TranslateTransform Y="0.614"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
</Border>
But it does nothing when running the application.
In the designer on the main window I have a StackPanel and then on it the other controls also Image control.
I want to show the user that there is a Image control like pictureBox the problem is when running the program and the Image is still empty there is nothing that indicate that there is a Image control. That's why I want to draw a rectangle on the Image borders.
You need to pick a brush for your Border.
<Border BorderThickness="1" BorderBrush="Black">
<Image x:Name="Img" HorizontalAlignment="Left" Height="233" Margin="467,54,0,0" VerticalAlignment="Top" Width="272" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform AngleY="0.704"/>
<RotateTransform/>
<TranslateTransform Y="0.614"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
</Border>
Actually, the method you applied is very close, since the picture will be in a border, it would be more logical to resize the border instead of resizing the picture. If you make an application like below, it will work for you.
<Border BorderThickness="2"
BorderBrush="Black"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Height="128"
Width="128">
<Image HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Stretch="Fill"
Source="/Images/antenna.png"/>
</Border>
It will be enough to have something like this in your application.
<Border BorderThickness="3" BorderBrush="Red" Height="233" Width="272">
<Image x:Name="Img" HorizontalAlignment="Left" Margin="467,54,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform AngleY="0.704"/>
<RotateTransform/>
<TranslateTransform Y="0.614"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
</Border>

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

Expander button on the right side: how to do it?

i want to position the Expander button on the right side of the label. How to do this?
You can also set the FlowDirection to RightToLeft, but that may cause other problems. For example it also changes the flow direction for the content of the expander so you may need to set it back.
<Expander FlowDirection="RightToLeft">
<StackPanel FlowDirection="LeftToRight">
</StackPanel>
</Expander>
You must restyle the control's template. Here's an example: http://patconroy.wordpress.com/2008/12/18/restyling-the-wpf-expander-control/
Another way to approach this is to position the expander where you like, without any header or content in the expander itself.
Then bind the visibility of your content-control to the expanders IsExpanded property, using a BooleanToVisibilityConverter.
<StackPanel>
<StackPanel.Resources>
<BooleanToVisibilityConverter x:Key="boolToVisibility" />
</StackPanel.Resources>
<DockPanel>
<Expander DockPanel.Dock="Right" x:Name="rightAlignedExpander" />
<TextBlock Text="Expanders header" VerticalAlignment="Center" />
</DockPanel>
<Grid Visibility="{Binding IsExpanded, ElementName=rightAlignedExpander, Converter={StaticResource boolToVisibility}}">
<TextBlock Text="Expanders content"/>
</Grid>
</StackPanel>
The downside is that it will not expand when the header is clicked, but that could easily be implemented if necessary.
Personally I think this is more simple and straightforward instead of completely restyling the control's template. It also have the added benefit that it will keep any styles already applied to the expander, for example when using 3rd party themes like DevExpress or Telerik.
You can use tranform commands to flip the Controls
<Expander RenderTransformOrigin="0.5,0.5">
<Expander.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleY="1" ScaleX="-1" />
<SkewTransform AngleY="0" AngleX="0" />
<RotateTransform Angle="0" />
<TranslateTransform />
</TransformGroup>
</Expander.RenderTransform>
<Expander.Header>
<Grid RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleY="1" ScaleX="-1" />
<SkewTransform AngleY="0" AngleX="0" />
<RotateTransform Angle="0" />
<TranslateTransform />
</TransformGroup>
</Grid.RenderTransform>
<TextBlock>Text</TextBlock>
</Grid>
</Expander.Header>
<Grid Height="100" RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleY="1" ScaleX="-1" />
<SkewTransform AngleY="0" AngleX="0" />
<RotateTransform Angle="0" />
<TranslateTransform />
</TransformGroup>
</Grid.RenderTransform>
<TextBlock>Text</TextBlock>
</Grid>
</Expander>

Resources