ScaleTransform on an image leaves whitespace - wpf

I'm creating a dialog with a single image, and a polygon overlaid. The problem is that the scale of the image is different from that of the polygon, so I want to scale the image down to match the scale of the polygon. But when I use the RenderTransform/ScaleTransform tags, the image gets sized down leaving whitespace at the right and bottom of the dialog. Yes the overlay now works properly, but I'd like to have it fill the available space to fill the window.
<Window x:Class="vw.CollImage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Collection Image" Height="700" Width="700"
WindowStartupLocation="CenterOwner" Grid.IsSharedSizeScope="False"
Icon="Resources\ty.ico">
<Viewbox MinWidth="70" MinHeight="70">
<Grid>
<Image Name="imgColl" HorizontalAlignment="Left" VerticalAlignment="Top" Source="{Binding ImageData}">
<Image.RenderTransform>
<ScaleTransform ScaleX="0.75" ScaleY="0.75"/>
</Image.RenderTransform>
</Image>
<Polyline Stroke="OrangeRed" StrokeThickness="6" Points="{Binding Coordinates}"/>
</Grid>
</Viewbox>
</Window>

Apply it as LayoutTransform instead.

Related

How can I use a XAML ellipse like a container for another shape?

I am creating a UserControl in WPF to model an eye (like a cartoon eye), and will move the "pupil" (black circle) around within the eye to look in certain directions. I would like to use the "white" part of the eye as the container for the "black" part of the eye, so that the black ellipse will be clipped as it gets to the edges of the eye, and won't just float outside of the white ellipse.
How can I do this in WPF/XAML?
You could use a Border with a large CornerRadius as the outer part of the eye and create an OpacityMask on that Border to make sure the inner eye is clipped to the Border
Quick Example:
<Window x:Class="WpfApplication9.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="121" Width="278" Name="UI">
<Grid Background="DarkGray" ClipToBounds="True">
<Border x:Name="opacityMask" CornerRadius="1000" Background="White" />
<Border CornerRadius="1000" Background="White" >
<Ellipse Width="50" Height="50" Fill="Black"/>
<Border.OpacityMask>
<VisualBrush Visual="{Binding ElementName=opacityMask}" />
</Border.OpacityMask>
</Border>
</Grid>
</Window>
Result:

Why is this clipping happening

Notice in the code i didn't put any clipping on the grid, why is this rectangle being displayed clipped to the size of the grid.
I added the offset just to show that even if i move it to the side the fill of the grid is not red.
<Grid Height="135" Width="162">
<Rectangle Width="300" Height="249" HorizontalAlignment="Center" VerticalAlignment="Center" Fill="#FFDB1919" UseLayoutRounding="False">
<Rectangle.Projection>
<PlaneProjection LocalOffsetX="-42"/>
</Rectangle.Projection>
</Rectangle>
</Grid>
Grids have clipping of content on by default.
The quickest fix is to place the rectangle in a canvas (which has no clipping by default):
<Grid Height="135" Width="162">
<Canvas>
<Rectangle Width="300" Height="249" HorizontalAlignment="Center" VerticalAlignment="Center" Fill="#FFDB1919" UseLayoutRounding="False" StrokeThickness="5">
<Rectangle.Projection>
<PlaneProjection LocalOffsetX="-42"/>
</Rectangle.Projection>
</Rectangle>
</Canvas>
</Grid>
This is what happening here:
1. WPF layout is done. it will place the
rectangle in the center as it was specified.
2. The rectangle will be clipped by the Grid.
3. The Projection transformation is applied after all this stuff.
In your case you did move already clipped rectangle by -42 pixels

RotateTransform on an Ellipse within a PivotItem

I'm new to WPF/Silverlight and I'm just playing about with my new Windows Phone 7.
I created a new Pivot application and changed it to the following code:
<Grid x:Name="LayoutRoot" Background="Transparent">
<!--Pivot Control-->
<controls:Pivot Title="MY APPLICATION">
<!--Pivot item one-->
<controls:PivotItem Header="first">
<Ellipse Width="300" Height="300" Fill="Red">
<Ellipse.RenderTransform>
<RotateTransform CenterX="150" CenterY="150" Angle="90"/>
</Ellipse.RenderTransform>
</Ellipse>
</controls:PivotItem>
<controls:PivotItem Header="second">
<Ellipse Width="300" Height="300" Fill="Blue"/>
</controls:PivotItem>
</controls:Pivot>
</Grid>
On the first pivot item, if you start your swipe over the ellipse, it is necessary to swipe upwards to move to the next pivotitem. If you begin the swipe somewhere outside of the ellipse, the swipe gesture is left right as expected.
I'm pretty sure that this is will be obvious to a XAML veteran, I'm not really sure how I should be preventing the gesture being affected by the RotateTransform too?
Any help appreciated.
Edit:
I think that I have figured this out. If I set IsHitTestVisible="False" on the Ellipse then it all works as expected.

TextBlock filling vertical space

I want to create a TextBlock (or some other element with text in it for display only) that is vertical (-90 transform angle), but I want that element to fill up the vertical space it is contained in, but have a defined horizontal amount (I'm using vertical and horizontal terms instead of height and width since it's swapped when I have the TextBlock go vertical), and have it aligned to the left side of the container.
I believe I understand how to make a TextBlock go vertical using RenderTransform or LayoutTransform. However, I cannot seem to get the 'docking' to work properly, whenever I change the vertical aspect of the container the TextBlock increases in horizontal aspect instead of vertical.
Here is what I have:
<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="AttendanceTracker.StudentView"
x:Name="UserControl" Height="172.666" Width="417.333">
<StackPanel x:Name="LayoutRoot" Orientation="Horizontal">
<Border BorderBrush="Black" BorderThickness="1" RenderTransformOrigin="0.5,0.5" Background="#52FFFFFF" Width="139.667">
<TextBlock Text="My Title" TextWrapping="Wrap" FontSize="18.667" TextAlignment="Center" Foreground="White" Margin="-58.509,68.068,49.158,70.734" Background="Black" RenderTransformOrigin="0.5,0.5" Width="147.017" d:LayoutOverrides="Height">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-90"/>
<TranslateTransform/>
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
</Border>
</StackPanel>
Change the height of the UserControl and you will notice that the TextBlock increases in horizontal aspect instead of the desired vertical aspect.
If I understand you correctly, then this should point you in the right direction:
<StackPanel Orientation="Horizontal">
<TextBlock Background="Red" Text="My Title">
<TextBlock.LayoutTransform>
<TransformGroup>
<RotateTransform Angle="90"/>
</TransformGroup>
</TextBlock.LayoutTransform>
</TextBlock>
</StackPanel>
The key is to use LayoutTransform, not RenderTransform. This will ensure that another layout pass occurs after the transform occurs. Otherwise, the layout system is using the original bounding rectangle to layout the TextBlock.
Beyond that, I just got rid of all the Blend-generated cruft to see what was going on. Here's the result:
alt text http://img187.imageshack.us/img187/1189/screenshottbv.png

How can you align a canvas background in WPF?

I have set a canvas' background to an image of a company logo. I would like for this image to be aligned to the bottom right corner of the canvas.
Is it possible to do this, or would it require for the image to be added into the canvas as a child? That would not work with this program as all children of the canvas are handled differently.
Thank You
Will this work? (It worked for me, anyway.)
<Canvas>
<Canvas.Background>
<ImageBrush ImageSource="someimage.jpg" AlignmentX="Right"
AlignmentY="Bottom" Stretch="None" />
</Canvas.Background>
</Canvas>
AFAIK The WPF Canvas needs child UI elements to be positioned using absolute co-ordinates.
To achieve the right-bottom-anchored effect, I think you'd need to handle the window resize event, recalculate and apply the Top,Left co-ordinates for the child Image element to always stick to the right buttom corner.
<Window x:Class="HelloWPF.Window1" xmlns...
Title="Window1" Height="300" Width="339">
<Canvas>
<Image Canvas.Left="195" Canvas.Top="175" Height="87" Name="image1" Stretch="Fill" Width="122" Source="dilbert2666700071126ni1.gif"/>
</Canvas>
</Window>
How about containing the canvas and image inside of a Grid control like so?
<Window ...>
<Grid>
<Canvas/>
<Image HorizontalAlignment="Right" VerticalAlignment="Bottom" .../>
<Grid>
</Window>
This is my solution using a border inside the canvas to align the image. This solution works well when canvas is resized:
<Canvas x:Name="MiCanvas" Height="250" Width="500" Background="Aqua">
<Border x:Name="MiBorderImage"
Width="{Binding ElementName=MiCanvas, Path=ActualWidth}"
Height="{Binding ElementName=MiCanvas, Path=ActualHeight}"
Background="Transparent">
<Image x:Name="MiImage" Source="/GraphicsLibrary/Logos/MiLogo.png"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Stretch="None" />
</Border>
</Canvas>

Resources