How to make a multipaged UserControl in WPF? - wpf

I'm trying to make a user control which contains three different pages, each displaying different content. My idea was to make the following: create the user control main grid, then create another grid with the width set to three times the width of the user control or the main grid, and then create three columns in it. Then I would create a grid for each of the columns, wrapping each page content. Next, create two buttons to slide the pages, changing them through a translate transform animation.
I did it all right, but the sliding doesn't work as I expected: when the grid is translated, the content of the new page doesn't get displayed, and the other page keeps visible in the side of the user control.
The code is as follows:
.cs
private void TranslateMainGrid(bool right)
{
DoubleAnimation gridTranslateAnimation = new DoubleAnimation(); // Calculations not important
gridTranslateAnimation.From = right ? 0 - (this.SelectedPanel - 1) * 286 : 0 - (this.SelectedPanel + 1) * 286;
gridTranslateAnimation.To = 0 - this.SelectedPanel * 286;
gridTranslateAnimation.Duration
= new Duration(new TimeSpan(0, 0, 0, 0, 500));
TranslateTransform oTransform
= (TranslateTransform)PanelGrid.RenderTransform;
oTransform.BeginAnimation(TranslateTransform.XProperty,
gridTranslateAnimation);
}
.xaml
<Grid x:Name="MainGrid" Height="400" Width="286" Background="#7B9D9D9D" RenderTransformOrigin="0.5,0.5">
<Grid x:Name="PanelGrid" Height="400" Width="858" RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<TranslateTransform X="0"/>
</Grid.RenderTransform>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid x:Name="ChimeraGrid" Grid.Column="0">
<Grid.Background>
<ImageBrush ImageSource="/GameView;component/Resources/arcaneCreature.png"/>
</Grid.Background>
</Grid>
<Grid x:Name="CreatureGrid" Grid.Column="1">
<Grid.Background>
<ImageBrush ImageSource="/GameView;component/Resources/chimeraTest.png"/>
</Grid.Background>
<Label Content="lolololol" Height="81" VerticalAlignment="Top" HorizontalAlignment="Right" Width="164"/>
</Grid>
<Grid x:Name="EquipmentGrid" Grid.Column="2">
<Grid.Background>
<ImageBrush ImageSource="/GameView;component/Resources/tribeCreature.png"/>
</Grid.Background>
</Grid>
</Grid>
</Grid>
The code was simplified, but I guess it ilustrates the whole stuff. How can I deal with this grids? Is there any other way to do what I intended here?
Thanks

Replace your top-level Grid
<Grid x:Name="MainGrid" Width="286" ...>
by a Canvas and set the ClipToBounds property:
<Canvas Name="MainCanvas" Width="286" ClipToBounds="True">
Moreover you have to set the Height property of those Grids in the three columns that don't have any content. Setting only the Background to an ImageBrush will not affect the Grid's size. The result is that the three Grids have Width=286 (resulting from 858 divided by three columns) but the left and right Grid have Height=0, because they have no content. The middle one gets its height from the contained Label and is hence visible.
Instead of setting an ImageBrush you could also put an Image control in each column Grid. Thus the heights of the three Grids would be set automatically.
Of course ClipToBounds also works with a Grid, but it seems that the Grid won't re-render any previously invisible parts of its content when a RenderTransform is applied to that content.
When using a Canvas you may also consider to animate the Canvas.Left property instead of using a TranslateTransform.
EDIT: Here is the XAML from my test program:
<Window x:Class="SlidingGrid.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="500" Width="400">
<Canvas Width="286" ClipToBounds="True" Margin="10">
<Grid Width="858" Name="grid" Canvas.Left="0" Height="400">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RenderTransform>
<TranslateTransform x:Name="slideTransform"/>
</Grid.RenderTransform>
<Grid Grid.Column="0">
<Grid.Background>
<ImageBrush ImageSource="C:\Users\Public\Pictures\Sample Pictures\Desert.jpg" Stretch="UniformToFill"/>
</Grid.Background>
</Grid>
<Grid Grid.Column="1">
<Grid.Background>
<ImageBrush ImageSource="C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg" Stretch="UniformToFill"/>
</Grid.Background>
</Grid>
<Grid Grid.Column="2">
<Grid.Background>
<ImageBrush ImageSource="C:\Users\Public\Pictures\Sample Pictures\Tulips.jpg" Stretch="UniformToFill"/>
</Grid.Background>
</Grid>
</Grid>
</Canvas>
</Window>
and the code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += (o, e) =>
{
//grid.BeginAnimation(
// Canvas.LeftProperty,
// new DoubleAnimation(-572, TimeSpan.FromSeconds(2)));
slideTransform.BeginAnimation(
TranslateTransform.XProperty,
new DoubleAnimation(-572, TimeSpan.FromSeconds(2)));
};
}
}

Related

Vlc.DotNet WPF video background issue

There is my code. I see the video in the top right corner, where control itself is located, but the main grid background is empty. It's supposed to take video through VisualBrush, right? I've googled few samples and they all use the same trick, but it doesn't work...
I've also tried to put some controls on top of the control, but nothing shows through, because I assume it's using WinForms control inside, which is top-most.
So how do I get this video as the background?
<Grid>
<vlc:VlcControl x:Name="myVlcControl" Width="100" Height="100" HorizontalAlignment="Right" VerticalAlignment="Top" />
<Grid>
<Grid.Background>
<VisualBrush Stretch="Uniform">
<VisualBrush.Visual>
<Image Source="{Binding VideoSource, ElementName=myVlcControl}" />
</VisualBrush.Visual>
</VisualBrush >
</Grid.Background>
</Grid>
MediaElement supports RTSP just fine, but it may not support the encoding/container you're trying to work with. The following produces a working streaming MediaElement, and uses a VisualBrush to paint the background of a Grid with the MediaElement:
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<MediaElement x:Name="MyPlayer"
Width="640"
Height="480"
LoadedBehavior="Play"
Source="rtsp://granton.ucs.ed.ac.uk/domsdemo/v2003-1.wmv" />
<Grid Grid.Row="1"
Width="320"
Height="240">
<Grid.Background>
<VisualBrush Stretch="Uniform" Visual="{Binding ElementName=MyPlayer}" />
</Grid.Background>
</Grid>
</Grid>
#Kolorowezworki made Airhack control to workaround this issue.
Example:
<airhack:AirControl DataContext="{Binding}">
<airhack:AirControl.Front>
<Image Source="{Binding VideoSource, ElementName=myVlcControl}" />
</airhack:AirControl.Front>
<airhack:AirControl.Back>
<vlc:VlcControl x:Name="myVlcControl" Width="100" Height="100" HorizontalAlignment="Right" VerticalAlignment="Top" />
</airhack:AirControl.Back>
</airhack:AirControl>
NOTE: By default AirControl does't support DataContext Binding, to solve this issue fork or copy repository and implement DataContext support by passing it 'airhack' window.
Example:
public AirControl()
{
InitializeComponent();
alpha = new Alpha(this);
alpha.DataContext = DataContext;
DataContextChanged += (sender, args) => alpha.DataContext = DataContext;
}

How to make all controls resize accordingly proportionally when window is maximized?

When I clicked on the maximize button the window is maximized but the controls are not resized proportionally. What is the best way to make the controls resize accordingly? I am using MVVM.
Here is my code.
<Window x:Class="DataTransfer.View.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Icon="/DataTransfer;component/View/Images/ms_msnexplore.gif"
ResizeMode="CanResizeWithGrip"
Title="Window1" Height="500" Width="600">
<!--Style="{DynamicResource OfficeStyle}"-->
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!--<ResourceDictionary Source="/DataTransfer;component/View/WindowBase.xaml" />-->
<!--<ResourceDictionary Source="/DataTransfer;component/Themes/WPFThemes/CalendarResource.xaml" />-->
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width ="*" />
</Grid.ColumnDefinitions>
<Button Content="Button" HorizontalAlignment="Left" Margin="52,28,0,0" VerticalAlignment="Top" Width="75" Height="22" />
<DatePicker Name="dp" HorizontalAlignment="Left" Margin="175,25,0,0" VerticalAlignment="Top" Width="123" Text="aaa" GotFocus="DateGotFocused" LostFocus="OnLeaveArchiveDate"/>
<Calendar HorizontalAlignment="Left" Margin="47,162,0,0" VerticalAlignment="Top"/>
<TextBox Name="t1" HorizontalAlignment="Left" Height="23" Margin="337,23,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" LostFocus="LeaveField" />
<RadioButton Content="RadioButton" HorizontalAlignment="Left" Margin="88,92,0,0" VerticalAlignment="Top"/>
<CheckBox Content="CheckBox" HorizontalAlignment="Left" Margin="252,96,0,0" VerticalAlignment="Top"/>
<ComboBox Name="combo" IsEditable="False" Text="aaa" IsReadOnly="True"
HorizontalAlignment="Left" Margin="337,89,0,0" VerticalAlignment="Top" Width="120"
Focusable="True" GotFocus="ComboBoxGotFocused" >
<ComboBoxItem>January</ComboBoxItem>
<ComboBoxItem>February</ComboBoxItem>
</ComboBox>
<TextBlock HorizontalAlignment="Left" Height="40" Margin="260,184,0,0" TextWrapping="Wrap" Text="Text_Block" VerticalAlignment="Top" Width="257"/>
</Grid>
</Window>
In WPF there are certain 'container' controls that automatically resize their contents and there are some that don't.
Here are some that do not resize their contents (I'm guessing that you are using one or more of these):
StackPanel
WrapPanel
Canvas
TabControl
Here are some that do resize their contents:
Grid
UniformGrid
DockPanel
Therefore, it is almost always preferable to use a Grid instead of a StackPanel unless you do not want automatic resizing to occur. Please note that it is still possible for a Grid to not size its inner controls... it all depends on your Grid.RowDefinition and Grid.ColumnDefinition settings:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100" /> <!--<<< Exact Height... won't resize -->
<RowDefinition Height="Auto" /> <!--<<< Will resize to the size of contents -->
<RowDefinition Height="*" /> <!--<<< Will resize taking all remaining space -->
</Grid.RowDefinitions>
</Grid>
You can find out more about the Grid control from the Grid Class page on MSDN. You can also find out more about these container controls from the WPF Container Controls Overview page on MSDN.
Further resizing can be achieved using the FrameworkElement.HorizontalAlignment and FrameworkElement.VerticalAlignment properties. The default value of these properties is Stretch which will stretch elements to fit the size of their containing controls. However, when they are set to any other value, the elements will not stretch.
UPDATE >>>
In response to the questions in your comment:
Use the Grid.RowDefinition and Grid.ColumnDefinition settings to organise a basic structure first... it is common to add Grid controls into the cells of outer Grid controls if need be. You can also use the Grid.ColumnSpan and Grid.RowSpan properties to enable controls to span multiple columns and/or rows of a Grid.
It is most common to have at least one row/column with a Height/Width of "*" which will fill all remaining space, but you can have two or more with this setting, in which case the remaining space will be split between the two (or more) rows/columns. 'Auto' is a good setting to use for the rows/columns that are not set to '"*"', but it really depends on how you want the layout to be.
There is no Auto setting that you can use on the controls in the cells, but this is just as well, because we want the Grid to size the controls for us... therefore, we don't want to set the Height or Width of these controls at all.
The point that I made about the FrameworkElement.HorizontalAlignment and FrameworkElement.VerticalAlignment properties was just to let you know of their existence... as their default value is already Stretch, you don't generally need to set them explicitly.
The Margin property is generally just used to space your controls out evenly... if you drag and drop controls from the Visual Studio Toolbox, VS will set the Margin property to place your control exactly where you dropped it but generally, this is not what we want as it will mess with the auto sizing of controls. If you do this, then just delete or edit the Margin property to suit your needs.
myCanvas is a Canvas control and Parent to all other controllers. This code works to neatly resize to any resolution from 1366 x 768 upward. Tested up to 4k resolution 4096 x 2160
Take note of all the MainWindow property settings (WindowStartupLocation, SizeToContent and WindowState) - important for this to work correctly - WindowState for my user case requirement was Maximized:
XAML:
<Window x:Name="mainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyApp"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
x:Class="MyApp.MainWindow"
Title="MainWindow" SizeChanged="MainWindow_SizeChanged"
Width="1366" Height="768" WindowState="Maximized" WindowStartupLocation="CenterOwner" SizeToContent="WidthAndHeight">
<Canvas x:Name="myCanvas" HorizontalAlignment="Left" Height="768" VerticalAlignment="Top" Width="1356">
<Image x:Name="maxresdefault_1_1__jpg" Source="maxresdefault-1[1].jpg" Stretch="Fill" Opacity="0.6" Height="767" Canvas.Left="-6" Width="1366"/>
<Separator Margin="0" Background="#FF302D2D" Foreground="#FF111010" Height="0" Canvas.Left="-811" Canvas.Top="148" Width="766"/>
<Separator Margin="0" Background="#FF302D2D" Foreground="#FF111010" HorizontalAlignment="Right" Width="210" Height="0" Canvas.Left="1653" Canvas.Top="102"/>
<Image x:Name="imgscroll" Source="BcaKKb47i[1].png" Stretch="Fill" RenderTransformOrigin="0.5,0.5" Height="523" Canvas.Left="-3" Canvas.Top="122" Width="580">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="89.093"/>
<TranslateTransform/>
</TransformGroup>
</Image.RenderTransform>
</Image>
.cs:
private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
{
myCanvas.Width = e.NewSize.Width;
myCanvas.Height = e.NewSize.Height;
double xChange = 1, yChange = 1;
if (e.PreviousSize.Width != 0)
xChange = (e.NewSize.Width / e.PreviousSize.Width);
if (e.PreviousSize.Height != 0)
yChange = (e.NewSize.Height / e.PreviousSize.Height);
ScaleTransform scale = new ScaleTransform(myCanvas.LayoutTransform.Value.M11 * xChange, myCanvas.LayoutTransform.Value.M22 * yChange);
myCanvas.LayoutTransform = scale;
myCanvas.UpdateLayout();
}
Well, it's fairly simple to do.
On the window resize event handler, calculate how much the window has grown/shrunk, and use that fraction to adjust 1) Height, 2) Width, 3) Canvas.Top, 4) Canvas.Left properties of all the child controls inside the canvas.
Here's the code:
private void window1_SizeChanged(object sender, SizeChangedEventArgs e)
{
myCanvas.Width = e.NewSize.Width;
myCanvas.Height = e.NewSize.Height;
double xChange = 1, yChange = 1;
if (e.PreviousSize.Width != 0)
xChange = (e.NewSize.Width/e.PreviousSize.Width);
if (e.PreviousSize.Height != 0)
yChange = (e.NewSize.Height / e.PreviousSize.Height);
foreach (FrameworkElement fe in myCanvas.Children )
{
/*because I didn't want to resize the grid I'm having inside the canvas in this particular instance. (doing that from xaml) */
if (fe is Grid == false)
{
fe.Height = fe.ActualHeight * yChange;
fe.Width = fe.ActualWidth * xChange;
Canvas.SetTop(fe, Canvas.GetTop(fe) * yChange);
Canvas.SetLeft(fe, Canvas.GetLeft(fe) * xChange);
}
}
}

Creating a sidebar - flyout like Windows desktop app in WPF

what i am trying to do is create a Desktop application in WPF whose UI is such that a small icon will remain fixed in the center of the left edge of screen and on click(or maybe hover) will slide open a sidebar(like the google desktop bar) running along the left edge of the screen (fixed position, cannot be moved).
do note that what i'm asking for might be like an appbar but i do not want the desktop icons along the left edge to be moved as it happens with an appbar i.e. i do not want it to hog up the desktop spacce....can anyone please suggest me a way out ??
I have implemented a partial solution using this, but i cant get the slide animation and fixed position to workout
Something like this could work:
then of course you could create a slide in animation for the sidebar. This shows (partial) transparency and the switching principle.
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowStyle="None" Topmost="True" WindowState="Maximized"
AllowsTransparency="True" Background="Transparent">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Rectangle Name="rect" Width="100" VerticalAlignment="Stretch" Fill="#99000000" Visibility="Collapsed" />
<Button Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" Width="32" Height="32" FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Right" Background="White" Click="Button_Click">></Button>
</Grid>
</Window>
C#:
private void Button_Click(object sender, RoutedEventArgs e)
{
if (rect.Visibility == System.Windows.Visibility.Collapsed)
{
rect.Visibility = System.Windows.Visibility.Visible;
(sender as Button).Content = "<";
}
else
{
rect.Visibility = System.Windows.Visibility.Collapsed;
(sender as Button).Content = ">";
}
}
Based on this answer and more answers on this site I made a side bar, I liked the result so i made a repo.
https://github.com/beto-rodriguez/MaterialMenu
you can install it from nuget too.
here is an example
<materialMenu:SideMenu HorizontalAlignment="Left" x:Name="Menu"
MenuWidth="300"
Theme="Default"
State="Hidden">
<materialMenu:SideMenu.Menu>
<ScrollViewer VerticalScrollBarVisibility="Hidden">
<StackPanel Orientation="Vertical">
<Border Background="#337AB5">
<Grid Margin="10">
<TextBox Height="150" BorderThickness="0" Background="Transparent"
VerticalContentAlignment="Bottom" FontFamily="Calibri" FontSize="18"
Foreground="WhiteSmoke" FontWeight="Bold">Welcome</TextBox>
</Grid>
</Border>
<materialMenu:MenuButton Text="Administration"></materialMenu:MenuButton>
<materialMenu:MenuButton Text="Packing"></materialMenu:MenuButton>
<materialMenu:MenuButton Text="Logistics"></materialMenu:MenuButton>
</StackPanel>
</ScrollViewer>
</materialMenu:SideMenu.Menu>
</materialMenu:SideMenu>

Vertically expand textbox automatically when text is too long

I am trying to mimic the Sticky Notes application in Windows 7. In the original application, if you type text into a Sticky Note and the text becomes too large (vertically, as in number of lines) to fit in the window, the window automatically expands vertically, one line at a time, to allow for more room. In other words, where in a normal Textbox a vertical scrollbar would appear and the text would scroll down (so that the first line becomes invisible), in the Sticky Notes the textbox expands exactly enough to fit the text so that no scrollbar appears. The scrollbar still appears when you manually resize the window afterwards, of course.
If you have Windows 7 just open the Sticky Notes application and type a few lines in the sticky note until it enlarges.
I am trying to mimic this effect but I'm having no luck. The problem seems that the actual Window should resize, not just the Textbox (I don't think WPF works this way, that a resize of a child element can 'force' the parent element to become larger? At least not for a Window, right?).
The contents of the Window at this point are such:
<Window Background="Transparent" BorderBrush="Transparent">
<!-- Transparent border to draw dropshadow on -->
<Border Background="Transparent" BorderBrush="Transparent">
<!-- Grid with UI elements -->
<Grid Margin="5" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="27" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Stickynote header -->
<Border ... />
<!-- Content -->
<Border Grid.Row="1">
<TextBox Text="{Binding ContentText}" ... />
</Border>
</Grid>
</Border>
</Window>
Does anybody know how I can achieve this effect? Thanks!
Try the Window Property SizeToContent="Height"
Sample
<Window ...
MaxHeight="500"
SizeToContent="Height">
<Border Background="Transparent" BorderBrush="Transparent">
<Grid Margin="5" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="27" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="1">
<TextBox AcceptsReturn="True" MinHeight="100"/>
</Border>
</Grid>
</Border>
</Window>
Edit
To use it with the TransparentWindow you posted, add transparentWindow.SizeToContent = SizeToContent.Manual in OnDragDelta (TransparentWindow.cs)
private static void OnDragDelta(object sender, DragDeltaEventArgs e)
{
TransparentWindow transparentWindow = (TransparentWindow)sender;
Thumb thumb = e.OriginalSource as Thumb;
transparentWindow.SizeToContent = SizeToContent.Manual;
if (thumb != null && transparentWindow.WindowState == WindowState.Normal)
{
//...
}
}

cloning the controls

I am designing a silverlight application in which i will have a rectangle control at the left side, when i click the rectangel and drag a copy of the rectangle control should be created and dragged and dropped in to the page.
Please can anyone help me with the code
For simplicity I'm going to leave out the Drag-Drop stuff since this question seems mainly about the cloning aspect.
The tool needed is the DataTemplate class. You place in a resource dictionary the set of items you want to clone each enclosed in a DataTemplate. You can use ContentPresenter to display instances of these items in say stack panel on the left. You can then use code to create instances of the template content and place them in say a Canvas on the right.
Example.
Xaml:-
<UserControl x:Class="SilverlightApplication1.CloningStuff"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<UserControl.Resources>
<DataTemplate x:Key="Rectangle">
<Rectangle Stroke="Blue" StrokeThickness="3" Fill="CornflowerBlue" Width="100" Height="75" />
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel>
<ContentPresenter x:Name="Rectangle" ContentTemplate="{StaticResource Rectangle}" />
</StackPanel>
<Canvas x:Name="Surface" MouseLeftButtonDown="Surface_MouseLeftButtonDown" Grid.Column="1" Background="Wheat">
</Canvas>
</Grid>
</UserControl>
Code:-
public partial class CloningStuff : UserControl
{
public CloningStuff()
{
InitializeComponent();
}
private void Surface_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Canvas target = (Canvas)sender;
Point p = e.GetPosition(target);
Rectangle r = (Rectangle)((DataTemplate)Resources["Rectangle"]).LoadContent();
Canvas.SetLeft(r, p.X);
Canvas.SetTop(r, p.Y);
target.Children.Add(r);
}
}
This shows using a ContentPresenter to display your rectangle. In place of drag-dropping (for which there are plenty of examples of elsewhere) this code just creates a Clone of the rectangle whereever the user clicks in the Canvas.

Resources