I am creating an app for the Microsoft Surface. I have a WPF control rotated 180 degrees using rendertransform so that people on the other side can use it. There are two of them, one rotated, one not. When a user selects a tab on the control, the control grows to accommodate the tab size. On the one that's not rotated, the height animation works correctly, growing "upward" toward the "top" of the screen. The rotated one grows in the same direction, toward the top as well, but it need to grow on the opposite direction. Both should grow towards the center of the screen.
Setup (They are legends on a map):
<SurfaceWindow>
<Canvas>
<UserControl />
<UserControl /> // rotated
<Map />
</Canvas>
</SurfaceWindow>
Is there a way to control the direction of a height animation?
Thanks,
Andrew
You don't need two controls : just one with, say, a 'Flipped' property (or a dependency property to use it in design time). When Flipped is True, you should set the rotation on your control and the VerticalAlignment to Top. when false, no rotation and VerticalAlignment to Bottom.
Solved.
Used LayoutTransform instead of RenderTransform
eg
Legend2.LayoutTransform = new RotateTransform(180);
instead of
Legend2.RenderTransform = new RotateTransform(180);
Related
In my WP7 app, I have a user control, with a grid, and an ellipse in the layout root:
<Grid x:Name="LayoutRoot">
<Grid x:Name="grdCircle">
<Ellipse x:Name="elCircle" Stroke="#FFB91515" Margin="5"/>
</Grid>
</Grid>
I drop this on my main page in the WP7 app, and it looks fine in landscape mode, but when I switch to portrait the width expands and the height contracts, so it is no longer a circle. What I want is for the circle to be the max size it can be regardless of the orientation and still stay a circle.
I've tried putting SizeChanged event on LayoutRoot, and setting the grdCircle width/height to whatever was smaller - the LayoutRoot actual width or the LayoutRoot actual height, but as soon as I do that, changing the orientation doesn't fire the SizeChanged event of LayoutRoot anymore because LayoutRoot also becomes smaller. How can I ensure that my ellipse is always a circle and grows/shrinks based on the orientation?
Edit:
By default, the LayoutRoot grid should have horizontal and vertical alignment set to stretch with margins of 0, so shouldn't the LayoutRoot grid always grow to the size of its container?
Maybe you should take adventage of OrientationChanged event of a Page?
Updated
I think that your control is filling all space that is available. If you change orientation then the amount of space is changing - as a result your control is not a square any more. That fact implicates that the ellipse changes its shape from circle to ellipse, because your ellipse is also trying to fill in all available space. To avoid this you can set Stretch property of an ellipse to Uniform. This should resolve your problem.
I would like use a panel whose children have coordinates specified as percentage of total panel's width/height. Moreover, I should be able to animate the coordinate property, for example to make a button move from 10% to 50% panel's width.
I've made 2 attempts:
Use a Grid and specify size as stars - this was not enough, because AFAIK by default WPF cannot animate distance properties specified by stars. I've found somewhere a custom class that enabled me to do so, it even worked, hovewer I consider that solution overly complicated an I am looking for something simpler.
Use a Canvas with fixed width and height and put it inside a Viewbox - this is a simple solution, but when resizing the Viewbox the whole content of Canvas is resized too. I want the content to have fixed size.
Is there a simple solution or should I implement my own panel (or maybe extend one of the existing ones, i.e. Canvas)?
Cheers!
I would:
subclass Canvas, perhaps calling it RelativeCanvas or RatioCanvas
add two attached properties: XRatio and YRatio
override ArrangeOverride and loop over all children. For each child, use their XRatio and YRatio along with the ActualWidth and ActualHeight of the RelativeCanvas to calculate and apply values for their Canvas.Left and Canvas.Top attached properties
You would use it as follows:
<local:RelativeCanvas>
<!-- the top-left of this button will be center of panel -->
<Button local:RelativeCanvas.XRatio="50" local:RelativeCanvas.YRatio="50"/>
</local:RelativeCanvas>
One thing you might like to add after you get that working is control over alignment. For example, I might to align the center of a control to the specified ratio, not its top-left corner.
There's one here: WPF Proportional Panel
I have a UserControl which has a quadratic Image as a Child. This Image is at the bottom of the UserControl, and half of it is clipped (e.g. the Control's Height is 400, Image's height is 200 and it is set to y=300).
Now, When I rotate the Image, it is still clipped like the way it was first. Like when rotating around 90 degrees, I suddenly have an Image which is only 100px wide.
It seems like the original clipping which was made because of the bounds of the UserControl, are applied forever.
How do I solve this problem? I hope I explained my problem understandable ;)
How are you rotating the image? If you are rotating using a RenderTransform, then WPF does not re-render what was already displayed on the screen - it simply rotates the pixels.
Instead, rotate the image using a LayoutTransform; this forces WPF to re-render the control given the new area it occupies, which should eliminate the clipping you see.
You can also call InvalidateMeasure() after applying render transform.
I have a StackPanel inside of a ScrollViewer.
I have a slider that does a scale transform on the stackpanel to allow zoom-in and zoom-out functionality. The problem is that when I zoom in, the scrollviewer doesn't treat the content as being 'bigger'.
So, if I scroll in a little and scroll as far right as I can go - it stops me before I get to the end of the content. If I zoom back out to the untransformed level, I see that it's stopping exactly at that point. If I zoom in a lot, I can only see a small fraction of my total content when I scroll all the way over.
I can change the TransformOrigin to control which side loses the most content; but I figure there should be some way for the scrollviewer (or another control?) to take care of it for me.
Are you doing render transform, or layout transform? You should be doing the latter.
I need to implement a Canvas which scales its contents according to its size. I know there is Viewbox, which scales everything inside of it. However I cannot use that, because some elements have a fixed size and cannot be scaled.
Also how can I bind the size of the Canvas to the parent element (for example a resizable window). There is sizeToContent for windows, I want the size fitting exactly the other way round. Also the canvas uses some drawing based on the size of the hosting element, how is redraw triggered and how can I ensure that it only draws if it gets a valid (or min) size?
If you don't specify any width or height to the canvas it automatically uses all the available space. This is because the default VerticalAlignment and HorizontalAlignment are set to Stretch.
What do you mean by canvas that scales it's contents according to it's size without scaling all the contents as some have fixed size?
Update after comments
If your drawing algorithm already scales the content to the canvas' height and width then all you need to do is to resize the canvas to fit the area I believe? In that case just remove the hardcoded height/width values and the canvas will resize to fit the container.
You might need to use ActualHeight/ActualWidth instead of Height/Width in the drawing algorithm after this though. ActualHeight/ActualWidth return the values that the layout container will give your canvas so these represents the values the canvas is drawn with.
I think you can find the answers to all your questions in my London Underground demo.
I'm doing this from memory, but if I recall correctly a Window uses either a Panel or a Canvas as part of it's ControlTemplate (in which lies the ContentPresenter), which means that a Canvas placed directly in a Window will have issues resizing automatically like it might elsewhere. There are a few basic ways to address this.
1 Write a new ControlTemplate for your Window to use. :(2 Place your content directly in the Window rather than in a Canvas inside the Window. :/
3 Do a by-name binding. :)
<MyWindow x:Name="topWindow">
<Canvas x:Name="topCanvas" Width="{Binding ElementName=topWindow, Path=ActualWidth}" Height="{Binding ElementName=topWindow, Path=ActualHeight}">
...Content...
</Canvas>
</MyWindow>
(As it happens, I often bind grids inside Canvases in this fashion, so I can easily animate items moving from one grid position to another.)