i'm trying conform mvvm structure when getting mouse position when on image in wpf application. mouse position should converted pixel location respect image.
i have working when image_mousemove in imagepositionview.xaml.cs, i'm @ bit of loss (even after trying read other threads) how achieve using mvvm structure.
i have added reference mvvmlight in hopes make task easier, have never used before..
this have far:
view:
i have added these references based on have seen:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:cmd="http://www.galasoft.ch/mvvmlight"
<usercontrol x:class="imagepixellocation.view.imagepositionview" 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:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:cmd="http://www.galasoft.ch/mvvmlight" xmlns:local="clr-namespace:imagepixellocation" mc:ignorable="d" d:designheight="600" d:designwidth="1000" background="white"> <grid> <viewbox horizontalalignment="center"> <grid name="colorimage"> <image x:name="imageondisplay" source="{binding colourimage}" stretch="uniformtofill" /> </grid> </viewbox> </grid> </usercontrol>
viewmodel:
viewmodelbase exposes inofitypropertychanged , idisposable
using system.windows; using system.windows.input; using system.windows.media; using system.windows.media.imaging; using galasoft.mvvmlight; namespace imagepixelview.viewmodel { class imagepositionviewmodel : viewmodelbase { private writeablebitmap colourbitmap = null; public imagesource colourimage { { return this.colourbitmap; } } public manualselectionviewmodel() { // open image writeablebitmap string path = @"c:\some\path\to\colorimage.png"; stream imagestreamsource = new filestream(path, filemode.open, fileaccess.read, fileshare.read); var decoder = new pngbitmapdecoder(imagestreamsource, bitmapcreateoptions.preservepixelformat, bitmapcacheoption.default); bitmapsource source = decoder.frames[0]; int width = source.pixelwidth; int height = source.pixelheight; int stride = source.format.bitsperpixel / 8 * width; byte[] data = new byte[stride * height]; source.copypixels(data, stride, 0); this.colourbitmap = new writeablebitmap(width, height, 96.0, 96.0, source.format, null); this.colourbitmap.writepixels(new int32rect(0, 0, width, height), data, stride, 0); } private void image_mousemove(object sender, mouseeventargs e) { bitmapsource bitmapimage = (bitmapsource)this.colourimage; string xcoord = (e.getposition(imageondisplay).x * bitmapimage.pixelwidth / imageondisplay.actualwidth).tostring(); string ycoord = (e.getposition(imageondisplay).y * bitmapimage.pixelheight / imageondisplay.actualheight).tostring(); system.diagnostics.debug.writeline("mouse location x:" + xcoord + ", y:" + ycoord); } } }
i guess main thing how access view element imageondisplay
within imagepositionviewmodel
.
i behaviour. first declare interface view model implement:
public interface imousecaptureproxy { event eventhandler capture; event eventhandler release; void onmousedown(object sender, mousecaptureargs e); void onmousemove(object sender, mousecaptureargs e); void onmouseup(object sender, mousecaptureargs e); } public class mousecaptureargs { public double x {get; set;} public double y { get; set; } public bool leftbutton { get; set; } public bool rightbutton { get; set; } }
and here's behaviour uses it:
public class mousecapturebehavior : behavior<frameworkelement> { public static readonly dependencyproperty proxyproperty = dependencyproperty.registerattached( "proxy", typeof(imousecaptureproxy), typeof(mousecapturebehavior), new propertymetadata(null, onproxychanged)); public static void setproxy(dependencyobject source, imousecaptureproxy value) { source.setvalue(proxyproperty, value); } public static imousecaptureproxy getproxy(dependencyobject source) { return (imousecaptureproxy)source.getvalue(proxyproperty); } private static void onproxychanged(dependencyobject d, dependencypropertychangedeventargs e) { if (e.oldvalue imousecaptureproxy) { (e.oldvalue imousecaptureproxy).capture -= oncapture; (e.oldvalue imousecaptureproxy).release -= onrelease; } if (e.newvalue imousecaptureproxy) { (e.newvalue imousecaptureproxy).capture += oncapture; (e.newvalue imousecaptureproxy).release += onrelease; } } static void oncapture(object sender, eventargs e) { var behavior = sender mousecapturebehavior; if (behavior != null) behavior.associatedobject.capturemouse(); } static void onrelease(object sender, eventargs e) { var behavior = sender mousecapturebehavior; if (behavior != null) behavior.associatedobject.releasemousecapture(); } protected override void onattached() { base.onattached(); this.associatedobject.previewmousedown += onmousedown; this.associatedobject.previewmousemove += onmousemove; this.associatedobject.previewmouseup += onmouseup; } protected override void ondetaching() { base.ondetaching(); this.associatedobject.previewmousedown -= onmousedown; this.associatedobject.previewmousemove -= onmousemove; this.associatedobject.previewmouseup -= onmouseup; } private void onmousedown(object sender, mousebuttoneventargs e) { var proxy = getproxy(this); if (proxy != null) { var pos = e.getposition(this.associatedobject); var args = new mousecaptureargs { x = pos.x, y = pos.y, leftbutton = (e.leftbutton == mousebuttonstate.pressed), rightbutton = (e.rightbutton == mousebuttonstate.pressed) }; proxy.onmousedown(this, args); } } private void onmousemove(object sender, mouseeventargs e) { var proxy = getproxy(this); if (proxy != null) { var pos = e.getposition(this.associatedobject); var args = new mousecaptureargs { x = pos.x, y = pos.y, leftbutton = (e.leftbutton == mousebuttonstate.pressed), rightbutton = (e.rightbutton == mousebuttonstate.pressed) }; proxy.onmousemove(this, args); } } private void onmouseup(object sender, mousebuttoneventargs e) { var proxy = getproxy(this); if (proxy != null) { var pos = e.getposition(this.associatedobject); var args = new mousecaptureargs { x = pos.x, y = pos.y, leftbutton = (e.leftbutton == mousebuttonstate.pressed), rightbutton = (e.rightbutton == mousebuttonstate.pressed) }; proxy.onmouseup(this, args); } } }
to use behaviour add target ui element , bind object implements proxy interface. in case made mainviewmodel implement interface bind that:
<!-- canvas must have background, if it's transparent --> <canvas background="white" xmlns:i="clr-namespace:system.windows.interactivity;assembly=system.windows.interactivity"> <i:interaction.behaviors> <behaviors:mousecapturebehavior proxy="{binding}" /> </i:interaction.behaviors>
the view model needs provide mouse handlers behaviour call, needs provide capture/release events behaviour respond when raised view model:
public class mainviewmodel : viewmodelbase, imousecaptureproxy { public event eventhandler capture; public event eventhandler release; public void onmousedown(object sender, mousecaptureargs e) {...} public void onmousemove(object sender, mousecaptureargs e) {...} public void onmouseup(object sender, mousecaptureargs e) {...} }
update: should self-evident, in case not: sender pass in capture , release events should same 1 received via mousedown/move/up handlers. event args passed capture/receive aren't used , can null.
Comments
Post a Comment