Using C#, can you drag a canvas in WPF? - c#

Can you drag a canvas in WPF? How do you set the position of the canvas? Here is what I got so far:
/// xaml
<Window x:Class="TestApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="350" Width="525"
WindowStyle="None" ResizeMode="NoResize" AllowsTransparency="True"
Background="Transparent" Loaded="MainWindow_Loaded">
<Canvas Name="ParentCanvas" Background="#FF6E798D">
</Canvas>
</Window>
/// code behind
public partial class MainWindow : Window
{
private Boolean isMouseCapture;
public MainWindow()
{
InitializeComponent();
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
this.ParentCanvas.MouseLeftButtonDown += new MouseButtonEventHandler(_MouseLeftButtonDown);
this.ParentCanvas.MouseLeftButtonUp += new MouseButtonEventHandler(_MouseLeftButtonUp);
this.ParentCanvas.MouseMove += new MouseEventHandler(_MouseMove);
}
void _MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
this.ParentCanvas.ReleaseMouseCapture();
isMouseCapture = false;
}
void _MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.ParentCanvas.CaptureMouse();
isMouseCapture = true;
}
void _MouseMove(object sender, MouseEventArgs e)
{
if (isMouseCapture)
{
this.ParentCanvas.X= e.GetPosition(this).X;
this.ParentCanvas.Y = e.GetPosition(this).Y;
}
}
}
'X' is not a property of Canvas (i.e."this.ParentCanvas.X"). What do I use to set the position?

To set the position of an element in pixels, the element must be contained in a Canvas panel.
You can then call Canvas.SetTop and Canvas.SetLeft.

Related

How do I assign a global initialized event?

I've got this code in my App.xaml.cs:
protected override void OnStartup(StartupEventArgs e)
{
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.TextChangedEvent, new RoutedEventHandler(TextBox_TextChangedEvent));
}
private void TextBox_TextChangedEvent(object sender, RoutedEventArgs e)
{
// Works
}
I would like to do something similar for the InitializedEvent.
Here's my failed attempt:
protected override void OnStartup(StartupEventArgs e)
{
EventManager.RegisterClassHandler(typeof(FrameworkElement), FrameworkElement.InitializedEvent, new EventHandler(FrameworkElement_InitializedEvent));
}
private void FrameworkElement_InitializedEvent(object sender, EventArgs e)
{
}
Is the InitializedEvent somewhere else?
Is this even possible?
I've tried using the LoadedEvent:
protected override void OnStartup(StartupEventArgs e)
{
EventManager.RegisterClassHandler(typeof(FrameworkElement), FrameworkElement.LoadedEvent, new RoutedEventHandler(FrameworkElement_LoadedEvent));
}
private void FrameworkElement_LoadedEvent(object sender, RoutedEventArgs e)
{
// Fires only for Windows
}
It only fired for Windows and not the controls inside the Windows. I did realize though; that when I added a loaded event to a Label that I had inside my Window; the global FrameworkElement_LoadedEvent fired for that Label even though my normal loaded event (That I made for the Label specifically) was empty. I've also tried these:
EventManager.RegisterClassHandler(typeof(Button), Button.LoadedEvent, new RoutedEventHandler(Button_LoadedEvent));
EventManager.RegisterClassHandler(typeof(Grid), Grid.LoadedEvent, new RoutedEventHandler(Grid_LoadedEvent));
EventManager.RegisterClassHandler(typeof(DataGrid), DataGrid.LoadedEvent, new RoutedEventHandler(DataGrid_LoadedEvent));
But they don't fire unless I add another empty loaded event on those controls specifically.
My goal is to build up a sort of a time log of every control that becomes initialized.
How can I achieve this without adding loaded events on every single control I have?
(I have a lot)
Here you are!
public partial class App : Application
{
// ##############################################################################################################################
// Constructor
// ##############################################################################################################################
#region Constructor
static App()
{
// set MyInitialized=true for new windows (happens before Loaded)
EventManager.RegisterClassHandler(typeof(Window), FrameworkElement.SizeChangedEvent, new RoutedEventHandler(OnSizeChanged));
// our loaded handler
EventManager.RegisterClassHandler(typeof(UIElement), FrameworkElement.LoadedEvent, new RoutedEventHandler(OnLoaded), true);
EventManager.RegisterClassHandler(typeof(ContentElement), FrameworkContentElement.LoadedEvent, new RoutedEventHandler(OnLoaded), true);
}
private static void OnSizeChanged(object sender, RoutedEventArgs e)
{
//Console.WriteLine("SizeChanged {0}", sender);
SetMyInitialized((Window) sender, true);
}
private static void OnLoaded(object sender, RoutedEventArgs e)
{
Trace.WriteLine($"{DateTime.Now:O}: {sender} loaded");
}
#endregion
// ##############################################################################################################################
// MyInitialized
// ##############################################################################################################################
#region MyInitialized
public static void SetMyInitialized(UIElement element, bool value)
{
element.SetValue(MyInitializedProperty, value);
}
public static bool GetMyInitialized(UIElement element)
{
return (bool) element.GetValue(MyInitializedProperty);
}
public static readonly DependencyProperty MyInitializedProperty = DependencyProperty.RegisterAttached("MyInitialized", typeof (bool), typeof (App), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits, OnMyInitializedChanged));
private static void OnMyInitializedChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs ev)
{
if ((bool)ev.NewValue)
{
// registering instance handler unbreaks class handlers
if (dpo is FrameworkElement element)
element.Loaded += _EmptyRoutedEventHandler;
if (dpo is FrameworkContentElement contentElement)
contentElement.Loaded += _EmptyRoutedEventHandler;
} else
{
throw new ArgumentException("Cannot set to false", ev.Property.Name);
}
//Console.WriteLine("MyInitialized {0} {1}=>{2}", dpo, ev.OldValue, ev.NewValue);
}
private static readonly RoutedEventHandler _EmptyRoutedEventHandler = delegate { };
#endregion
}
XAML
<Window x:Class="WpfApp3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp3"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
d:DataContext="{d:DesignInstance local:MainWindow}">
<Grid>
<Border Background="Green" VerticalAlignment="Center" HorizontalAlignment="Center" Width="30" Height="20">
<TextBlock Background="Orange" Text="hello"></TextBlock>
</Border>
</Grid>
</Window>
Sample Console output:
2018-07-31T14:20:52.6052225+02:00: WpfApp3.MainWindow loaded
2018-07-31T14:20:52.6112064+02:00: System.Windows.Controls.Border loaded
2018-07-31T14:20:52.6132008+02:00: System.Windows.Documents.AdornerDecorator loaded
2018-07-31T14:20:52.6141984+02:00: System.Windows.Controls.ContentPresenter loaded
2018-07-31T14:20:52.6141984+02:00: System.Windows.Controls.Grid loaded
2018-07-31T14:20:52.6151966+02:00: System.Windows.Controls.Border loaded
2018-07-31T14:20:52.6161935+02:00: System.Windows.Controls.TextBlock loaded
2018-07-31T14:20:52.6161935+02:00: System.Windows.Documents.AdornerLayer loaded

One way dependency property changed notification

I'm trying to make a user control with a dependency property. I need to execute certain logic when the dependency property is changed from outside the usercontrol, but that logic shouldn't execute when the dependency property is changed from inside the user control. I have this small sample. I only want to execute certain logic when the value is set from mainwindow and not when it is set by clicking the checkbox. I don't know if PropertyChangedCallbackis the correct way, but this is what I have.
UserControl:
public partial class UserControl1 : UserControl
{
public int MyProperty
{
get { return (int)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(int), typeof(UserControl1), new PropertyMetadata(new PropertyChangedCallback(OnPropertyChanged)));
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Only process the 5, don't process the 6
}
public UserControl1()
{
InitializeComponent();
}
private void checkBox_Click(object sender, RoutedEventArgs e)
{
MyProperty = 6;
}
}
UserControl xaml:
<UserControl x:Class="WpfApplication4.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<CheckBox x:Name="checkBox" Click="checkBox_Click"/>
</Grid>
</UserControl>
MainWindow:
public partial class MainWindow : Window
{
public int MainWindowProperty { get; set; }
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
MainWindowProperty = 5;
}
}
Mainwindow xaml:
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication4"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:UserControl1 MyProperty="{Binding MainWindowProperty}"/>
</Grid>
</Window>
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!disableProcessing)
{
// Only process the 5, don't process the 6
}
}
bool disableProcessing = false;
private void checkBox_Click(object sender, RoutedEventArgs e)
{
disableProcessing = true;
MyProperty = 6;
disableProcessing = false;
}

WPF: Canvas swallowing MouseDownEvent?

Can anybody please explain to me why theMouseDownevent is not reaching theScrollViewerin this easy example?
<Window x:Class="MouseDownTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ScrollViewer Name="scrollViewer" Background="Green" MouseDown="ScrollViewer_MouseDown" PreviewMouseDown="ScrollViewer_PreviewMouseDown">
<Canvas Name="canvas" Background="Beige" MouseDown="Canvas_MouseDown" PreviewMouseDown="Canvas_PreviewMouseDown">
</Canvas>
</ScrollViewer>
</Grid>
</Window>
code behind:
using System;
using System.Windows;
using System.Windows.Input;
namespace MouseDownTest
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
scrollViewer.AddHandler(MouseDownEvent, new RoutedEventHandler(ScrollViewer_Test));
}
private void ScrollViewer_Test(object sender, RoutedEventArgs routedEventArgs)
{
Console.WriteLine("ScrollViewer_Test");
}
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
Console.WriteLine("Canvas_MouseDown");
}
private void Canvas_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
Console.WriteLine("Canvas_PreviewMouseDown");
}
private void ScrollViewer_MouseDown(object sender, MouseButtonEventArgs e)
{
Console.WriteLine("ScrollViewer_MouseDown");
}
private void ScrollViewer_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
Console.WriteLine("ScrollViewer_PreviewMouseDown");
}
}
}
Output when clicking canvas is
ScrollViewer_PreviewMouseDown
Canvas_PreviewMouseDown
Canvas_MouseDown
Why isScrollViewer_MouseDownbeing omitted? I already looked into this article but the solution given there does not help (or I did it wrong).
You will probably need to set Focusable="False" on the ScrollViewer to allow the mouse events to pass though
<ScrollViewer Name="scrollViewer" Focusable="False" Background="Green" />
Output:
ScrollViewer_PreviewMouseDown
Canvas_PreviewMouseDown
Canvas_MouseDown
ScrollViewer_MouseDown

How to display a PictureBox from behind code in C#

I know my question sounds basic, but i searched all over the place and found nothing..
this is my code :
public MainWindow()
{
InitializeComponent();
Map newMap = new Map();
newMap.setMapStrategy(new SmallMapStrategy());
newMap.createMap();
System.Windows.Forms.PictureBox pictureBox1 = new System.Windows.Forms.PictureBox();
pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(newMap.grid[3].afficher);
}
this is the afficher function :
public override void afficher(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(squareImage, pos_x, pos_y, 50, 50);
}
squareImage is an attribute corresponding to a Drawing.Image.
pos_x and pos_y are custom int32 attributes.
What i'd like is to SEE the image while running my application...
Since the PictureBox that you are using is a Winforms Control you will need to add a WindowsFormsHost Control to your Wpf Form and add the PictureBox to that. Any time you dynamically create a control you need to add it to the Form or Container object otherwise it will not be shown.
But first, add these references:
System.Windows.Forms
WindowsFormsIntegration
Now write code something like this.
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<WindowsFormsHost Height="175" HorizontalAlignment="Left" Margin="10,10,0,0" Name="windowsFormsHost1" VerticalAlignment="Top" Width="255" />
</Grid>
</Window>
MainWindow.xaml.cs
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
System.Windows.Forms.PictureBox picturebox1 = new System.Windows.Forms.PictureBox();
windowsFormsHost1.Child = picturebox1;
picturebox1.Paint += new System.Windows.Forms.PaintEventHandler(picturebox1_Paint);
}
void picturebox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(#"C:\Temp\test.jpg");
System.Drawing.Point ulPoint = new System.Drawing.Point(0, 0);
e.Graphics.DrawImage(bmp,ulPoint);
}
}
}

dynamically assigning an event

I am dynamically creating a GroupBox and trying to assign the MouseLeftButtonDown event to it to perform some action when the user left-clicks on it. This is what I've tried:
public MyClass()
{
tagGroupBox.MouseLeftButtonDown += new MouseButtonEventHandler(tagGroupBox_MouseLeftButtonDown); //generates error: "tagGroupBox_MouseLeftButtonDown does not exist in the current context"
}
private void tagGroupBox__MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Left click event triggered");
}
There are __ (double underscores) in handler method.
void tagGroupBox_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
}
This works for me:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
GroupBox g = new GroupBox();
g.MouseLeftButtonUp += new MouseButtonEventHandler(g_MouseLeftButtonUp);
MainGrid.Children.Add(g);
}
void g_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
System.Diagnostics.Debugger.Break();
}
}
XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="MainGrid">
</Grid>
</Window>

Categories

Resources