wpf - I've created a ellipse in c#...bt i want to move ellipse around the canvas using mouse.....can anyone help? And i'm new to c# -
i've created ellipse in c#, want move ellipse around canvas using mouse. can help? i'm new c#.
here's code.
private ellipse drawellipse(canvas acanvas) { ellipse newellipse = new ellipse(); newellipse.width = 10; newellipse.height = 10; newellipse.fill = new solidcolorbrush(colors.royalblue); acanvas.children.add(newellipse); newellipse.setvalue(canvas.leftproperty, acanvas.actualwidth / 2.0); newellipse.setvalue(canvas.topproperty, acanvas.actualheight / 2.0); return newellipse; }
i'm new wpf i'll explain understood far , how ellipse. since i'm wpf beginner too, explanation may approximatation please don't burn me alive. post may long
wpf , mvvm
first, have "view", xaml code (a description language xml-like syntax. each tag correspond class in .net framework) , design you'll see. when using wpf, should try implement mvvm pattern. in pattern, design of windows isn't matter of c# code, it's matter of "view" component, xaml code. have "viewmodel" component prepare datas kind of parameters view. last component model, things behind have nothing user interface.
coding view c# (like did) called "code behind" , mvvm pattern mistake in of cases.
the view "bind" viewmodel. when binded, view know viewmodel class , can use fields , properties. best thing using view models when modify variable viewmodel binded view, automatically update view.
drawing , drag'n'drop , ellipse
here exemple of view ellipse :
in canvasoverlayview.xaml
<usercontrol x:class="overlay.views.canvasoverlayview" 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" xmlns:viewmodels="clr-namespace:overlay.viewmodels" d:datacontext="{d:designinstance type=viewmodels:canvasoverlayviewmodel}" mc:ignorable="d"> //you can declare mouse event this, appropriate event handlers in .xaml.cs file // <canvas mousedown="uielement_onmousedown" mousemove="uielement_onmousemove" mouseup="uielement_onmouseup"> // use separated file viewmodel use : <i:interaction.triggers> <i:eventtrigger eventname="mousedown"> <i:invokecommandaction command="{binding path=datacontext.mousedowncommand}" commandparameter="{binding elementname=canvasoverlayview}"/> </i:eventtrigger> <i:eventtrigger eventname="mouseup"> <i:invokecommandaction command="{binding path=datacontext.mouseupcommand}" commandparameter="{binding elementname=canvasoverlayview}"/> </i:eventtrigger> <i:eventtrigger eventname="mousemove"> <i:invokecommandaction command="{binding path=datacontext.mousemovecommand}" commandparameter="{binding elementname=canvasoverlayview}"/> </i:eventtrigger> <path stroke="{binding color}" strokethickness="{binding thickness}"> <path.data> <ellipsegeometry center="{binding center}" radiusx="{binding radiusx}" radiusy="{binding radiusy}"/> </path.data> </path> </canvas>
to details :
x:class="overlay.views.canvasoverlayview"
precise name of associated canvasoverlayview.xaml.cs (it's partial class c# needed draw describe xaml file if understood correctly). can use file viewmodel seems better in separated file, i'll in exemple. xaml.cs empty (set datacontext , initialise component).
xmlns:viewmodels="clr-namespace:overlay.viewmodels"
alias namespace have viewmodel name viewmodels. used find viewmodel @ next line
d:datacontext="{d:designinstance type=viewmodels:canvasoverlayviewmodel}" datacontext class instance binding operation datas. here set datacontext (the source of parameters if want) right viewmodel. each view got own viewmodel
interaction.triggers here i'll create triggers command. command allow me handle event in viewmodel (if used xaml.cs viewmodel instead of totally separate .cs file, wouldn't need this).
pay attention binding syntax, use """parameters""" coming viewmodel.
path , ellipsegeometry
one of way draw ellipse. use way because prefered work center , radius of ellipse instead of canvas.setleft, width, height etc... makes drag operation easier (just need update center in viewmodel , tadaaaam, ellipse moved).
in canvasoverlayview.xaml.cs
namespace overlay.views { public partial class canvasoverlayview { public canvasoverlayview() { datacontext = new canvasoverlayviewmodel(); initializecomponent(); } } }
here give instance of viewmodel datacontext.
in canvasoverlayviewmodel.cs
first , important thing : viewmodel have implement inotifypropertychanged interface. interface essential since makes binded properties update automatically view. here minimal implementation exemple of use in property.
using system.componentmodel; namespace overlay.viewmodels { public class canvasoverlayviewmodel : inotifypropertychanged { private int exemple; public int exemple { { return exemple; } set { exemple = value; onpropertychanged(nameof(exemple)); // important } } public event propertychangedeventhandler propertychanged; protected void onpropertychanged(string propertyname) => propertychanged?.invoke(this, new propertychangedeventargs(propertyname)); } }
with this, if have "{binding exemple}" in xaml, updated automatically when change exemple value in viewmodel.
for ellipse, can create class contain parameters of ellipse, instance in viewmodel , bind in view.
commands , event
here exemple of handling events command, view exemple above. not way use icommand of course.
private icommand m_mousedowncommand; private icommand m_mousemovecommand; private icommand m_mouseupcommand; private bool canmove private point center; // binded center property of ellipsegeometry in view. public point center { { return center; } set { center = value; onpropertychanged(nameof(exemple)); } } // first parameter method handle event, second bool method define if event triggerable. // delegatecommand custom class implementing icommand, i'll give code below. public icommand mousedowncommand => m_mousedowncommand ?? (m_mousedowncommand = new delegatecommand(onmousedown, canmousedown)); public icommand mousemovecommand => m_mousemovecommand ?? (m_mousemovecommand = new delegatecommand(onmousemove, canmousemove)); public icommand mouseupcommand => m_mouseupcommand ?? (m_mouseupcommand = new delegatecommand(onmouseup, canmouseup)); private bool canmousedown(object parameter) { return true; } private bool canmousemove(object parameter) { return canmove; } private bool canmouseup(object parameter) { return true; } private void onmousedown(object parameter) { canmove = true; } private void onmousemove(object parameter) { // ellipsegeometry center property updated ! center = mouse.getposition((iinputelement)parameter); } private void onmouseup(object parameter) { canmove = false; }
i'll give delegatecommand class :
using system; using system.windows.input; public class delegatecommand : icommand { private readonly action<object> m_command; private readonly predicate<object> m_canexecute; public delegatecommand(action<object> command, predicate<object> canexecute = null) { if (command == null) { throw new argumentnullexception("command", "the delegate command null"); } m_canexecute = canexecute; m_command = command; } public event eventhandler canexecutechanged { add { commandmanager.requerysuggested += value; } remove { commandmanager.requerysuggested -= value; } } public void execute(object parameter) { m_command(parameter); } public bool canexecute(object parameter) { return m_canexecute == null || m_canexecute(parameter); } }
i hope explanation clear. sorry if it's not 200% technically accurate, i'm new @ wpf. way among many, not best. tell me if not clear or if somethig can made more accurate.
Comments
Post a Comment