Why is this clipping happening - silverlight

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

Related

Canvas is clipped when size is too big

I am using a canvas with the an ImageBrush to dispaly an image. I am setting the size of the canvas to the original size of the image so I can get the coordinates when I move the mouse etc.
The problem is that when I put the canvas in a control (Grid for example) with a smaller size the Canvas is clipped.
<Grid>
<Canvas Width="{Binding ImageWidth}" Height="{Binding ImageHeight}" >
<Canvas.Background>
<ImageBrush ImageSource="{Binding Image, Converter={StaticResource imgConverter}}"/>
</Canvas.Background>
</Canvas>
</Grid>
Is there a way to keep the canvas size without being clipped?
I've been meaning to dig deeper in to the source to work out where the clipping occurs for a while now, but never get around to doing it. I've been using a not-so-nice trick of inserting a Canvas into the visual tree when this happens as a workaround.
There are a number of controls that clip the child visuals; Grid, StackPanel, etc. As I mentioned the usual quick fix is to use a Canvas after the container that causes the clip.
In your snippet are there more containers higher up the visual tree?
If the depth was actually something like this:-
<StackPanel>
<Grid>
<Canvas Width="{Binding ImageWidth}" Height="{Binding ImageHeight}" >
<Canvas.Background>
<ImageBrush ImageSource="{Binding Image, Converter={StaticResource imgConverter}}"/>
</Canvas.Background>
</Canvas>
</Grid>
</StackPanel>
Then this might cause clipping. If you insert another Canvas further up the visual tree then this clipping is removed.
<StackPanel>
<Canvas>
<Grid>
<Canvas Width="{Binding ImageWidth}" Height="{Binding ImageHeight}" >
<Canvas.Background>
<ImageBrush ImageSource="{Binding Image, Converter={StaticResource imgConverter}}"/>
</Canvas.Background>
</Canvas>
</Grid>
</Canvas>
</StackPanel>
This workaround can then become problematic if it alters other layout needs for other controls.

wpf stretch a line when resizing the canvas parent

I have a vertical line and a horizontal one that i want to resize when i dynamically resize my canvas parent. (landmark)
i'd like to have the horizontal line always 25 away from the left and right borders of my canvas and 13 away from the bottom border.
and the same for the vertical line, 25 away from the top and bottom borders and 13 from the left border.
Is there a simple solution?
May I have to change my canvas to another control?
Just stick the lines in a grid on top of your canvas to get the right behaviour
<Grid Width="600" Height="600">
<Canvas Background="LightBlue">
// stuff here
</Canvas>
<Grid>
<Rectangle Fill="Black" Height="1"
Stroke="Black" VerticalAlignment="Bottom" Margin="25,0,25,13"/>
<Rectangle Fill="Black"
HorizontalAlignment="Left" Stroke="Black" Width="1" Margin="13,25,0,25"/>
</Grid>
</Grid>
I would use Converters based on the ActualHeight and ActualWidth of your Canvas to set the height, width, and position of your Line objects
To avoid writing a bunch of individual converters, I have a MathConverter posted on my blog that can be used for all the calculations.
<Canvas x:Name="MyCanvas">
<!-- Horizontal Line: 25 from each side, and 13 from bottom -->
<!-- May need to adjust the Canvas.Top ConverterParameter based on Line height -->
<Line Height="1"
Canvas.Left="25"
Canvas.Top="{Binding ElementName=MyCanvas, Path=ActualHeight,
Converter={StaticResource MathConverter},
ConverterParameter=#VALUE-14}"
Width="{Binding ElementName=MyCanvas, Path=ActualWidth,
Converter={StaticResource MathConverter},
ConverterParameter=#VALUE-50}" ... />
<!-- Vertical Line: 25 from top and bottom, and 13 from left -->
<Line Canvas.Left="13" Canvas.Top="25"
Height="{Binding ElementName=MyCanvas, Path=ActualHeight,
Converter={StaticResource MathConverter},
ConverterParameter=#VALUE-50}" ... />
</Canvas>
Because these are all Bindings, they will get refreshed anytime the bound property changes (MyCanvas.ActualHeight and MyCanvas.ActualWidth)
Use Grid instead of Canvas in the case you need to set Margin.
For your lines to have space from the borders, go to Properties and use Margin in the Layout Area to set the spaces. For your horizontal line set the VerticalAlignment to Bottom and HorizontalAlignment to Stretch. The Margin shall be 25,0,25,13 in this case.
for your vertical line set the VerticalAlignment to Stretch an the HorizontalAlignment to Left. Margin should be 13,25,0,25
have luck

Silverlight: Centering After ScaleTransform

I learned how to get a ScrollViewer's scrollbars to display after scaling an element within in a ScrollViewer from this post: http://www.eightyeightpercentnerd.dreamhosters.com/?p=92
Now, I'm trying to get the scaled object (a canvas in this case) to center correctly within the ScrollViewer. I'm going to let images tell my story here (please help me before Screencast.com purges my files). ;
My XAML:
<ScrollViewer x:Name="ScrollViewer" VerticalAlignment="Top"
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"
Width="300" Height="300" Margin="0" Padding="0" Background="White">
<Canvas x:Name="DesignSurface" Background="Red">
<Canvas x:Name="Surface" Background="Blue" Height="100" Width="100">
<Canvas.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="SurfaceScaleTransform" />
</TransformGroup>
</Canvas.RenderTransform>
<!-- ... -->
</Canvas>
</Canvas>
</ScrollViewer>
On initial load, my blue canvas is centered and at 100%:
After decreasing by 50%, the blue canvas is still centered:
After increasing 400% and scrolling to display the top left corner of the blue canvas:
After increasing 400% and scrolling to display the bottom right corner of the blue canvas:
So my question is simply how do I get the blue canvas centered correctly in the ScrollViewer or red canvas or whatever?
Maybe I got you wrong, but have you tried setting RenderTransformOrigin to the Canvas? E.g.:
<Canvas x:Name="Surface" Background="Blue" Height="100" Width="100"
RenderTransformOrigin="0.5, 0.5">
<Canvas.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="SurfaceScaleTransform" />
</TransformGroup>
</Canvas.RenderTransform>
<!-- ... -->
</Canvas>

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>

How to incorporate Canvas into a larger layout in WPF?

Canvas doesn't seem to play well together nicely with the other elements when you try to build it into a layout and have e.g. controls on the side and the canvas is the drawing area.
For instance, why can I put a border around every element except a canvas? In the following code, border wraps canvas but the canvas only has the border on the top but not on the left, right or bottom:
<Window x:Class="WpfApplication25.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<StackPanel>
<TextBlock DockPanel.Dock="Bottom" Text="Move the slider to reveal the answer:"/>
<Slider DockPanel.Dock="Bottom" Name="theSlider"
HorizontalAlignment="Left"
Width="200"
Minimum="0"
Maximum="1"
Value="1"
Cursor="Hand"/>
<Border BorderBrush="Tan" BorderThickness="2">
<Canvas>
<TextBlock Canvas.Left="45" Canvas.Top="50" Text="test" FontSize="16"/>
<Rectangle
Canvas.Left="10"
Canvas.Top="10"
Width="100"
Height="100"
Fill="Silver"
Opacity="{Binding ElementName=theSlider, Path=Value}"
/>
</Canvas>
</Border>
</StackPanel>
</Window>
From what I can tell in XamlPad, the problem appears to be that your Canvas does not have an explicit height/width, and that its HorizontalAlignment defaults to being in the middle of the Border. Without an explicit height and width the Border appears to collapse to 0 height and stretches on the width. My assumption is this is because your Border is in a StackPanel, as placing the Border in a Grid, causes it to behave as expected.
Your best bet is to give the Canvas an explicit Height and Width. Not sure that is what you're looking for though.
As far as I understand what you are trying to achieve, you should place your controls in one cell of a Grid and your Canvas in another.

Resources