I would like to paint Images to the XAML page in Windows Store App.
The main goal is that:
Adding Images (e.g. flower leaf) to a circle on the center like that:
I have a simple solution to that, but its is very redundant.
<Image Height="200" Width="200" Source="{Binding ActualImage.NormalUri}">
<Image.RenderTransform>
<RotateTransform Angle="12"></RotateTransform>
</Image.RenderTransform>
</Image>
... // And 28 other like these
<Image Height="200" Width="200" Source="{Binding ActualImage.NormalUri}">
<Image.RenderTransform>
<RotateTransform Angle="360"></RotateTransform>
</Image.RenderTransform>
</Image>
How can I do that with a binding of a Image collection? What XAML control should I use?
Use a custom class which inherits from ItemsControl. You can then override the necessary functions, such as ones to determine the angle to rotate between each item. I think it's likely you'll want to use this PrepareContainerForItemOverride for this.
One thing to note that you will have to do is to define a new ItemsPanel. The default is a StackPanel, which will not work. You'll likely want to use something like a Canvas, which allows you to explicitly position items in it.
The Solution of Nate Diamond is much more nicer and better, but I solved it from code-behind for earn the easier way:
foreach (Petal petalObject in MainPageViewModel.Petals)
{
var petalImage = new Image
{
Height = petalObject.Height,
Width = petalObject.Width,
RenderTransform = new RotateTransform() {Angle = petalObject.Angle},
Source = new BitmapImage(new Uri(petalObject.NormalUri)),
};
PetalsGrid.Children.Add(petalImage);
}
Related
Currently I am filling my MainWindow with a slightly transparent black:
But I want it to have a "hole" where this effect doesn't take place which should look like the following:
So this needs to be done at runtime since the area which the hole represents is going to change multiple times while the program is running.
What I thought I could do
So at first I thought I could just cut the area in the middle out
like you could do with a Graphics object, but the slightly
transparent black is nothing but a rectangle which is added as a child on a canvas which is currently done like this:
var background = new System.Windows.Shapes.Rectangle
{
Fill = new SolidColorBrush(System.Windows.Media.Color.FromArgb(150, 0, 0, 0)),
Width = ScreenInfo.Width,
Height = ScreenInfo.Height
};
MainCanvas.Children.Add(background);
But I couldn't fine any way to achieve this cut effect.
Creating 4 Rectangles which would look something like this: but this way of doing it didn't seem to me as the most effecient way of achieving this.
Thanks for any kind of help!
Create a CombinedGeometry by cutting a smaller square out of a larger one and then use that with a path. How you size it will depend on your application, a Viewbox will probably be good enough for most cases:
<Grid>
<TextBlock Text="Hello World!" FontSize="200" Foreground="Red" TextWrapping="Wrap" TextAlignment="Center"/>
<Viewbox Stretch="UniformToFill">
<Path Fill="#C0000000">
<Path.Data>
<CombinedGeometry GeometryCombineMode="Exclude">
<CombinedGeometry.Geometry1>
<RectangleGeometry Rect="0,0,4,4" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<RectangleGeometry x:Name="cutRect" Rect="1,1,2,2" />
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
</Viewbox>
</Grid>
Then to change the size of the inner geometry you can either bind its Rect to a view model property or change it directly in code-behind:
cutRect.Rect = new Rect(1, 1, 1, 1);
When I run this code in WPF it gives me 1/4 of a circle. When removing the ClipToBounds tag, i get my whole circle.
1. Why is it clipping before rendering?
2. How to i fix that, while keeping clipping?
<Canvas ClipToBounds="True">
<Ellipse Canvas.Left="-10"
Canvas.Top="-10"
Width="20"
Height="20"
Fill="LightSeaGreen"/>
<Canvas.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="4.8"
ScaleY="4.8"
CenterX="0"
CenterY="0"/>
<TranslateTransform X="48"
Y="48"/>
</TransformGroup>
</Canvas.RenderTransform>
</Canvas>
Why is it clipping before rendering?
It's not.
As you can see from here:
Your Ellipse is rendered perfectly. The ClipToBounds="True" is what ruins is as you can see from your Canvas:
How to i fix that, while keeping clipping?
This is quite a broad question. Your problem comes from the fact you are putting your Ellipse outside the Canvas (Canvas.Left="-10" Canvas.Top="-10") and then you clip it. Explain what is your goal and I can try to help you out.
This behaviour is by design. The authors of the textbook (Computer Graphics: Principles and Practice - Third Edition) have confusingly introduced ClipToBounds in a way that makes it seem like it is a part of the examples that follow in the book. In fact, they are not using ClipToBounds="True". You can verify that by downloading their lab package from http://sklardevelopment.com/graftext/ChapWPF2D/ .
To illustrate, here is the actual source code for one of their examples:
<Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="ClockCanvas" >
<Ellipse
Width="20.0" Height="20.0"
Canvas.Left="-10.0" Canvas.Top="-10.0"
Fill="lightgray"/>
</Canvas>
Note that there is no ClipToBounds="True" on the canvas.
I'm trying to implement zoom-functionality in a RadSlideView ItemTemplate. I'm doing this by using a ViewportControl with a Canvas and then applying a RenderTransform (ScaleTransform) to a StackPanel in the Canvas. Similar to the SDK-sample found here.
The problem I have is that the ScaleTransform seems to be affecting the swipe-gesture used to change item in the SlideView/Panorama/Pivot control. E.g. if the ScaleTransform is set to 0.1 it seems like I only need to swipe 1/10th of the length to change item compared to using a ScaleTransform of 1.0.
I found that if I set IsHitTestVisible to false on the ItemTemplate the swiping works like I want. But this is not a solution since I sometimes need to be able to pan the content vertically while still being able to change item by swiping horizontally.
So my question is how can I solve this?
For reference the XAML looks like this:
<Controls:RadSlideView Name="SlideView" ItemsSource="{Binding Pages}" IsLoopingEnabled="False" SelectionChanged="RadSlideView_SelectionChanged" CacheMode="BitmapCache" ManipulationStarted="SlideView_ManipulationStarted" ManipulationCompleted="SlideView_ManipulationCompleted" ManipulationDelta="SlideView_ManipulationDelta">
<Controls:RadSlideView.ItemTemplate>
<DataTemplate>
<ViewportControl x:Name="SlideViewViewport" ViewportChanged="SlideViewViewport_ViewportChanged" Loaded="SlideViewViewport_Loaded">
<Canvas>
<StackPanel>
<Image Source="{Binding Image}" Stretch="Fill" Width="{Binding ElementName=SlideView, Path=DataContext.PageWidth}" Height="{Binding ElementName=SlideView, Path=DataContext.PageHeight}" CacheMode="BitmapCache"/>
<StackPanel.RenderTransform>
<ScaleTransform x:Name="xform"/>
</StackPanel.RenderTransform>
</StackPanel>
</Canvas>
</ViewportControl>
</DataTemplate>
</Controls:RadSlideView.ItemTemplate>
I have also looked at Teleriks RadPanAndZoom-control to avoid implementing my own zoom-functionality, but since I sometimes need to place two pictures side by side and zoom them as if they were one I don't think I can use it.
The problem is that ScaleTransformation scales your picture, but doesn't change it's height and width. Only if Height And Width are overflowing scrollviewer you can scroll the content
I am using c# wpf for windows surface 2.0.
I have been working with a set of images that i import in the xmpl file.
I found some examples for text, but for the images they used GDI+ to manipulate images and animate them, but I do not want that.
The main thing that I want to do now is to rotate(transform rotate) an image and show that it is rotating.
Here is how I am addressing the images:
Canvas.SetTop(image1, 0);
Canvas.SetLeft(image1, 200);
Any help would be much appreciated.
Thank you.
If you want to rotate your image automatically and without user interaction, check Clemens' answer. However if you want to rotate with touch manipulations, I find it easy to put the image in a ScatterViewItem like so:
<s:ScatterView>
<s:ScatterViewItem CanMove="False" CanScale="False">
<s:ScatterViewItem.Background>
<ImageBrush ImageSource="yourImage.png" Stretch="UniformToFill"/>
</s:ScatterViewItem.Background>
</s:ScatterViewItem>
</s:ScatterView>
Of course, you have the overhead of having to put in a ScatterView and its content
Your question is not very specific and there are a lot of ways to animate the rotation of an image.
A simple approach would be to assign a RotateTransform to the RenderTransform of your Image controls and then animate the Angle property of these RotateTransforms.
<Image x:Name="image" Source="..."
RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<RotateTransform/>
</Image.RenderTransform>
</Image>
Start the animation in code like this:
var transform = (RotateTransform)image.RenderTransform;
var animation = new DoubleAnimation(360, TimeSpan.FromSeconds(5));
transform.BeginAnimation(RotateTransform.AngleProperty, animation);
You may start reading about animations in WPF in the Animation Overview article on MSDN. The Transforms Overview article may also be helpful.
I have an image in a WPF window with the default Stretch setting, Uniform, and am making an attempt to make it fill the screen horizontally. I do not wish to use a different Stretch setting as this is supposed to a learning experience. The image dimensions being loaded are 420x800. This is the XAML for the window..
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Red" Height="1200" Width="840">
<Image Name="Image" Source="{Binding SourceUri}">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="Scale" />
<TranslateTransform x:Name="Translate" />
</TransformGroup>
</Image.RenderTransform>
</Image>
</Window>
On the code-behind, I am attempting to calculate the scaling to zoom the image to fill the horizontal screen and I am using translate transform the move it to the center of the screen. The following bit of code is obviously wrong...
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace WpfApplication1 {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
DataContext = this;
double ImageWidth = 420;
Scale.ScaleX = Width / ImageWidth;
Translate.X = -(ImageWidth / 2);
}
public string SourceUri {
get {
return #"C:\Users\Roel\Desktop\test.png";
}
}
}
}
I am attempting to understand how stretching and transformations are working together but I am having difficulty with this. I would appreciate all insights, even references to detailed explanations, as I have trouble finding any informational source explaining clearly and concisely how the transformations are applied.
You would usually just do this:
<Image Name="Image" Source="{Binding SourceUri}" Stretch="Fill"/>
In case you really need to calculate the stretch transformation manually, you would only need a ScaleTransform, no TranslateTransform, and you would put that into the LayoutTransform of the Image control. Moreover, the Image control would have to be placed into a Grid, which provides the size of the Windows's "client area". You can't calculate anything based on the Window's Width (or ActualWidth) as that includes the width of the Window's borders.
<Grid SizeChanged="Grid_SizeChanged">
<Image Name="image" Source="{Binding SourceUri}">
<Image.LayoutTransform>
<ScaleTransform x:Name="scale"/>
</Image.LayoutTransform>
</Image>
</Grid>
In the Grid's SizeChanged handler you would calculate the scaling as shown below.
private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
{
scale.ScaleX = e.NewSize.Width / image.Source.Width;
scale.ScaleY = e.NewSize.Height / image.Source.Height;
}