I have a canvas, and I need to put an (for example) ellipse on it, not from XAML but from code. So I do
Ellipse e1;
public MainWindow()
{
...
...
e1 = new Ellipse();
e1.Height = 100;
e1.Width = 100;
e1.Stroke = Brushes.Red;
e1.StrokeThickness = 5;
Canvas.SetLeft(e1,40);
Canvas.SetTop(e1,50);
e1.MouseDown += ellipse_MouseDown;
Canvas1.Children.Add(e1);
}
private void ellipse_MouseDown(object sender, MouseButtonEventArgs e)
{
Ellipse el = (Ellipse)sender;
el.Stroke = Brushes.Green;
buttonAdd.Content = "New_TEXT";
}
But it doesn't react on clicking. Anyway, I tried to add this ellipse_MouseDownmethod to ellipse that was created from XAML - and it works.
<Canvas x:Name="Canvas1" HorizontalAlignment="Left" Height="421" Margin="10,10,0,0" VerticalAlignment="Top" Width="346">
<Ellipse x:Name="ellipse" Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="111" Margin="117,152,0,0" Stroke="Black" VerticalAlignment="Top" Width="131" MouseDown="ellipse_MouseDown" MouseMove="ellipse_MouseMove" MouseUp="ellipse_MouseUp"/>
</Canvas>
Where can be a problem?
UPD.
According to Rohit Vats's answer just add
e1.Fill = Brushes.Transparent;
or
e1.Fill = new SolidColorBrush((Color)ColorConverter
.ConvertFromString("#FFF4F4F5"));
'cause by default Fill is null which doesn't respond to mouse events
You need to set Fill to Transparent so that it can react to mouse events. By default Fill is null which doesn't respond to mouse events -
e1.Stroke = Brushes.Red;
e1.Fill = Brushes.Transparent; <-- HERE
UPDATE
As evident from XAML code, you are setting Fill to #FFF4F4F5 but not setting it from code behind.
e1.Fill = new SolidColorBrush((Color)ColorConverter
.ConvertFromString("#FFF4F4F5"));
Related
I am able to dynamically add images into the WPF Canvas control as child elements but failing to drag & drop those images inside the canvas. Please help me as how could i move or drag/drop images inside the canvas window.
Thanks in advance.
Below is what I have done so far:
<Canvas x:Name="canvasImages" Height="325" Margin="0,0,0,0" Width="430"
HorizontalAlignment="Left" VerticalAlignment="Top" AllowDrop="True"
PreviewMouseLeftButtonDown="MouseLeftButtonDown"
PreviewMouseLeftButtonUp="MouseLeftButtonUp"
PreviewMouseMove="MouseMove"
MaxWidth="430" MaxHeight="325"
ScrollViewer.HorizontalScrollBarVisibility="Visible"/>
</Grid>
**Code**
OpenFileDialog op = new OpenFileDialog();
op.Title = "Select Multiple Pictures";
op.Multiselect = true;
op.Filter = "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) |
*.jpg; *.jpeg; *.jpe; *.jfif; *.png";
foreach (string imageFile in op.FileNames)
{
Image img = new Image();
img.Source = new BitmapImage(new Uri(imageFile));
img.Height = 100;
img.Width = 100;
img.AllowDrop = true;
Canvas.SetTop(img, y); //Setting up images to the Top position
Canvas.SetLeft(img, x); //Setting up images to the left position
canvasImages.Children.Add(img);
}
private new void MouseLeftButtonDown(object sender,
MouseButtonEventArgs
e)
{
IsDragging = true;
draggedItem = (UIElement)sender;
itemRelativePosition = e.GetPosition(draggedItem);
}
private new void MouseMove(object sender,
System.Windows.Input.MouseEventArgs e)
{
if (!IsDragging)
return;
Point canvasRelativePosition = e.GetPosition(canvasImages);
Canvas.SetTop(draggedItem, canvasRelativePosition.Y -
itemRelativePosition.Y);
Canvas.SetLeft(draggedItem, canvasRelativePosition.X -
itemRelativePosition.X);
}
private new void MouseLeftButtonUp(object sender, MouseButtonEventArgs
e)
{
if (!IsDragging)
return;
IsDragging = false;
}
Ok, a few things wrong here...
1) Your mouse down handler has to be on the image, not the canvas, otherwise your code has no way of knowing which item is being dragged.
2) Once you've clicked on an image the handler should capture the mouse for the canvas so that you get all mouse move messages.
3) The Canvas MouseMove and MouseUp handlers then need to be handled accordingly.
4) The Canvas needs to have a background. If you don't give it a background then it's effectively transparent to the hit-testing and you won't get mouse messages for it. If you don't want it to have a visible background then set it to Transparent.
So your Canvas tag needs to look like this:
<Canvas x:Name="canvasImages" Height="325" Margin="0,0,0,0" Width="430"
HorizontalAlignment="Left" VerticalAlignment="Top" AllowDrop="True"
PreviewMouseLeftButtonUp="CanvasImages_PreviewMouseLeftButtonUp"
PreviewMouseMove="CanvasImages_PreviewMouseMove"
MaxWidth="430" MaxHeight="325"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
Background="Transparent" />
And every image you create needs to have a handler set for it's MouseDown event:
img.MouseLeftButtonDown += Img_MouseLeftButtonDown;
Then it's just a matter is implementing your handlers like this:
private void Img_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.draggedItem = (UIElement)sender;
itemRelativePosition = e.GetPosition(this.draggedItem);
e.Handled = true;
}
private void CanvasImages_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (this.draggedItem == null)
return;
var newPos = e.GetPosition(canvasImages) - itemRelativePosition;
Canvas.SetTop(this.draggedItem, newPos.Y);
Canvas.SetLeft(this.draggedItem, newPos.X);
canvasImages.CaptureMouse();
e.Handled = true;
}
private void CanvasImages_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (this.draggedItem != null)
{
this.draggedItem = null;
canvasImages.ReleaseMouseCapture();
e.Handled = true;
}
}
#Mark, Here are the XAML code and the respective Class for your perusal. Basically I am allowing multiple selection of images by "OpenFileDialog()" and adding those images dynamically to Canvas control as mentioned in my previous code, which then i am failing to drag around those images internally within the Canvas control.
Below is the XAML Code
<Window x:Class="PicturesMovement.CanvasControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Connectlite Clients"
Height="394" Width="445"
WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
<Grid Margin="0,0,2,0" Background="{DynamicResource {x:Static
SystemColors.MenuBarBrushKey}}">
<Button x:Name="Select" Content="Select" HorizontalAlignment="Left"
Height="22" Margin="329,328,0,0" VerticalAlignment="Top" Width="42"
Click="SelectImages"/>
<Button x:Name="Cancel" Content="Cancel" HorizontalAlignment="Left"
Margin="374,328,0,0" VerticalAlignment="Top" Width="49"
Click="closeBox"/>
<Canvas x:Name="canvasImages" Height="325" Margin="0,0,0,0"
Width="430" HorizontalAlignment="Left" VerticalAlignment="Top"
AllowDrop="True" PreviewMouseDown="PreviewMouseDown"
PreviewMouseUp="PreviewMouseUp"
PreviewMouseMove="PreviewMouseMove" MaxWidth="430"
MaxHeight="325"
ScrollViewer.HorizontalScrollBarVisibility="Visible"/>
</Grid>
</Window>
Below are the respective Class that triggers those Mouse Events
public partial class CanvasControl : System.Windows.Window,
System.Windows.Markup.IComponentConnector {
this.canvasImages.PreviewMouseDown += new
System.Windows.Input.MouseButtonEventHandler
(this.PreviewMouseDown);
this.canvasImages.PreviewMouseUp += new
System.Windows.Input.MouseButtonEventHandler
(this.PreviewMouseUp);
this.canvasImages.PreviewMouseMove += new
System.Windows.Input.MouseEventHandler
(this.PreviewMouseMove);
}
Any suggestions will be highly appreciated...Thanks
Im trying to bind my usercontrols (that have a move on mouse left btn logic inside its code behind) margin inside a datatemplate of an itemscontrol. However when being bound inside the datatemplate it doesnt update itself when a move on the grid behind it (which itself is a usercontrol aswell and has a move on mouse middle button logic inside its code behind).
The code behind of those is: (where in the grid it reacts to middle mouse)
private void Control_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
isDragging = true;
var draggableControl = sender as UserControl;
lasttransform = new Point(0, 0);
clickPosition = e.GetPosition(this.Parent as UIElement);
draggableControl.CaptureMouse();
}
private void Control_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (isDragging == true)
{
isDragging = false;
var draggable = sender as UserControl;
draggable.ReleaseMouseCapture();
completetransform = Point.Add(completetransform,new Vector( lasttransform.X, lasttransform.Y));
lasttransform = new Point(0, 0);
}
}
private void Control_MouseMove(object sender, MouseEventArgs e)
{
var draggableControl = sender as UserControl;
if (isDragging && draggableControl != null && draggableControl.GetType() == typeof(BaseNode))
{
Point currentPosition = e.GetPosition(this.Parent as UIElement);
currentPosition = new Point(currentPosition.X, currentPosition.Y);
var transform = draggableControl.RenderTransform as TranslateTransform;
if (transform == null)
{
transform = new TranslateTransform();
draggableControl.RenderTransform = transform;
}
transform.X = completetransform.X + (currentPosition.X - clickPosition.X);
transform.Y = completetransform.Y + (currentPosition.Y - clickPosition.Y);
lasttransform = new Point((currentPosition.X - clickPosition.X), (currentPosition.Y - clickPosition.Y));
}
}
}
When i now want to show my controls in some window like:
<Grid>
<my:EventGrid x:Name="XDisplayedEventGrid" Margin="-20" DataContext="{Binding DisplayedEventGrid}"/>
<Grid Background="Red" Width="100" Height="100" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="{Binding DisplayedEventGrid.ActualTransform, Converter={StaticResource ResourceKey=PointToMarginConverter}}"/>
<my:BaseNode HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="100" Margin="{Binding DisplayedEventGrid.ActualTransform, Converter={StaticResource ResourceKey=PointToMarginConverter}}"/>
<ItemsControl ItemsSource="{Binding DisplayedNodes}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<my:BaseNode HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="100" Margin="{Binding ElementName=XDisplayedEventGrid, Path=ActualTransform, Converter={StaticResource ResourceKey=PointToMarginConverter}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Where 'my:EventGrid 'is the movable grid, 'my:BaseNode' is a control to test everything and DataTemplate> my:BaseNode .../> /DataTemplate> is the actual displaying control for these usercontrols.
What should happen:
1) When you move the grid behind the visual brush makes it look like you can scroll unlimitedly.
2) The 'Grid Background="Red"' stays at its place on the eventgrid.
3) The Margin is bound to the eventgrid's moved coordinates which is translated to a margin by a converter, so for the user it looks like the controls stay on place on the grid and get moved out of view if the user looks at another portion of the grid.
4) When a node is moved its RenderTransform is set so it can be placed by and bound to a margin while being able to reposition it locally with the RenderTransform.
My Problem now is, that when the test-node has no DataContext bound it has the behavior of the grid and moves accordingly, but if it has one set it acts like the node inside the datatemplate and stays at 0,0 of the window.
The Datacontext of the node is an empty class deriving of a standard implementation of INotifyPropertyChanged.
When not having a datacontext bound inside the datatemplate it still has the same wrong behavior.
Where is my error and
are there any better controls to store externally marged usercontrols?
Thanks
ShinuSha
I learning WPF and build an simple application.
This is my button:
<Button x:Name="btnAddFiles" Content="Add" HorizontalAlignment="Left" Margin="1046,34,0,0" VerticalAlignment="Top"
Width="111" Height="34" FontSize="20" Foreground="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}"
Background="{x:Null}" MouseEnter="btnAddFiles_MouseEnter" BorderBrush="Transparent" />
And this is how it looks like:
http://s27.postimg.org/h0iq4mrrz/image.png
I have changed the button background color to Transparent so the background color the you see is all my application background color.
All i want to do is when the mouse is over the button change the background color to Transparent.
Currently this is the current when mouse is over:
http://s30.postimg.org/x61ssujnx/image.png?noCache=1411485462
So i registered to MouseEnter event:
private void btnAddFiles_MouseEnter(object sender, MouseEventArgs e)
{
//btnAddFiles.Background = // change the color
}
But i can see that btnAddFiles.Background require Brush and nor Color
Any idea hot to change it ?
i couldn't see your pictures but this is how we change back color in wpf:
btnAddFiles.Background = Brushes.Transparent;
and you can use your code in a mouse enter and mouse leave event.
1st Edit
private void btnAddFiles_MouseEnter(object sender, MouseEventArgs e)
{
btnAddFiles.Background = Brushes.Transparent;
}
private void btnAddFiles_MouseLeave(object sender, MouseEventArgs e)
{
btnAddFiles.Background = Brushes.Lime;
}
2nd Edit:
for changing border color and thickness:
button1.BorderBrush = Brushes.Red;
Thickness t = new Thickness(5, 5, 5, 5);
button1.BorderThickness = t;
also change your margin, it is out form. try for example
Margin="50,50,0,0"
let me know if you get your answer.
I got a working code for scaling frameworkelements in WPF via the ManipulationDelta method. It works with all kind of elements, as buttons, shapes or textblock, but not with textboxes.
Does anybody know how I can fix it?
Edit: Here´s a simpified Version of my Code:
private void canvas_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
var element = e.Source as FrameworkElement;
var transformation = element.RenderTransform as MatrixTransform;
var matrix = transformation == null ? Matrix.Identity : transformation.Matrix;
matrix.ScaleAt(e.DeltaManipulation.Scale.X,
e.DeltaManipulation.Scale.Y,
1,
1);
}
matrix.RotateAt(e.DeltaManipulation.Rotation,
e.ManipulationOrigin.X,
e.ManipulationOrigin.Y);
matrix.Translate(e.DeltaManipulation.Translation.X,
e.DeltaManipulation.Translation.Y);
element.RenderTransform = new MatrixTransform(matrix);
e.Handled = true;
}
The elements are created genericly, but it´s the same as this xaml:
<Canvas Name="SomeCanvas" ManipulationDelta="canvas_ManipulationDelta">
<TextBox Canvas.Left="400" Canvas.Top="200" Height="50" Name="s3" IsManipulationEnabled = "true" Background="#57FF3ACB" />
</Canvas>
This is because TextBox handles MouseDown events internally. They never get called, so the manipulation can't work. Here is the explanation:
http://msdn.microsoft.com/es-es/library/ms750580(v=vs.85).aspx
Alternatively, you could wrap the TextBox in a Border:
<Canvas Name="SomeCanvas" ManipulationDelta="canvas_ManipulationDelta">
<Border Canvas.Left="400" Canvas.Top="200" Background="Transparent" IsManipulationEnabled="True">
<TextBox Height="50" Name="s3" Background="#57FF3ACB" IsHitTestVisible="False" />
</Border>
</Canvas>
Put the IsHitTestVisible property to False in order to let the Mouse events pass from the TextBox to the Border.
Furthermore, you need to set the Border's Background to make it hit test visible.
Im trying to draw a line with finger on windows phone canvas, i Done this but when i try to remove/clear that line it's Removing all Elements in that Canvas ,
ContentPanelCanvas.Children.Clear();
Hear is My Complete Code:
XAML
<Canvas x:Name="ContentPanelCanvas" Grid.Row="1" Background="Transparent" Margin="12,0,12,0">
<Grid Width="450" Height="600">
<Button x:Name="clickMeBtn" Height="72"
Width="200"
Content="Click Me"
HorizontalAlignment="Center"
VerticalAlignment="Center" Click="clickMeBtn_Click" />
</Grid>
</Canvas>
C# Code is Like this :
public MainPage()
{
InitializeComponent();
this.ContentPanelCanvas.MouseMove += new MouseEventHandler(ContentPanelCanvas_MouseMove);
this.ContentPanelCanvas.MouseLeftButtonDown += new MouseButtonEventHandler(ContentPanelCanvas_MouseLeftButtonDown);
}
void ContentPanelCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
currentPoint = e.GetPosition(ContentPanelCanvas);
oldPoint = currentPoint;
}
void ContentPanelCanvas_MouseMove(object sender, MouseEventArgs e)
{
currentPoint = e.GetPosition(this.ContentPanelCanvas);
line = new Line() { X1 = currentPoint.X, Y1 = currentPoint.Y, X2 = oldPoint.X, Y2 = oldPoint.Y };
line.Stroke = new SolidColorBrush(Colors.White);
line.StrokeThickness = 10;
this.ContentPanelCanvas.Children.Add(line);
oldPoint = currentPoint;
}
private void clickMeBtn_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Hello Every One ");
ContentPanelCanvas.Children.Clear();
}
Code is Executing Without Error , But it's Removing button to , How can i Remove Only Lines I Draw
Well, the code is doing exactly what you wrote, it is clearing all children of the ContentPanelCanvas. If you only want to remove the lines, then only remove the lines:
foreach (var line in ContentPanelCanvas.Children.OfType<Line>().ToList())
ContentPanelCanvas.Children.Remove(line);
You can use
ContentPanelCanvas.Children.Remove(Line);
or remove children by index
ContentPanelCanvas.Children.RemoveAt(1);
If you clear the canvas it will "Removes all elements from a UIElementCollection."
You should create an event handler with line for example tap event handler , once tap you should hold the line control in another control to remove, then in button click handler remove it like this
ContentPanelCanvas.Children.Remove(controlToDelete);
controlToDelete is the control you hold to delete from the line tap handler i.e line control