Reputation: 7
I am programming an application where I can crop and resize an image by mouse. Because I had problems figuring out how I could pass Event Args in MVVM, I decided to give MVVM Light a try. Now everytime my mouse is over the image I receive the error:
An unhandled exception of type 'System.InvalidCastException' occurred in GalaSoft.MvvmLight.Platform.dll
Additional information: Das Objekt des Typs "System.Windows.Point" kann nicht in Typ "System.Windows.Input.MouseEventArgs" umgewandelt werden.
I don't really know how to fix this although I assume that my RelayCommands are implemented wrong.
I did the bindings in the XAML as following:
<Image x:Name="_image" Margin="10" Source="{Binding CurrentImage.ImagePath, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Left" VerticalAlignment="Top" Stretch="Fill" MaxHeight="300">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<cmd:EventToCommand Command="{Binding Mode=OneWay, Path=MouseDownCommand}"
EventArgsConverter="{StaticResource MouseButtonEventArgsToPointConverter}"
EventArgsConverterParameter="{Binding ElementName=_image}"
PassEventArgsToCommand="True" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseMove">
<cmd:EventToCommand Command="{Binding Mode=OneWay, Path=MouseMoveCommand}"
EventArgsConverter="{StaticResource MouseEventArgsToPointConverter}"
EventArgsConverterParameter="{Binding ElementName=_image}"
PassEventArgsToCommand="True" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseUp">
<cmd:EventToCommand Command="{Binding Mode=OneWay, Path=MouseUpCommand}"
EventArgsConverter="{StaticResource MouseButtonEventArgsToPointConverter}"
EventArgsConverterParameter="{Binding ElementName=_image}"
PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Image>
My ViewModel looks like this:
RelayCommand<MouseButtonEventArgs> mouseDownCommand;
public RelayCommand<MouseButtonEventArgs> MouseDownCommand
{
get
{
if (mouseDownCommand == null)
{
mouseDownCommand = new RelayCommand<MouseButtonEventArgs>(MouseDown);
}
return mouseDownCommand;
}
}
public void MouseDown(MouseButtonEventArgs e)
{
this.currentImage.StartPoint = e.GetPosition(this.currentImage.CnvImage);
}
RelayCommand<System.Windows.Input.MouseEventArgs> mouseMoveCommand;
public RelayCommand<System.Windows.Input.MouseEventArgs> MouseMoveCommand
{
get
{
if (mouseMoveCommand == null)
{
mouseMoveCommand = new RelayCommand<System.Windows.Input.MouseEventArgs>(MouseMove);
}
return mouseMoveCommand;
}
}
public void MouseMove(System.Windows.Input.MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
var pos = e.GetPosition(this.currentImage.CnvImage);
var x = Math.Min(pos.X, this.currentImage.StartPoint.X);
var y = Math.Min(pos.Y, this.currentImage.StartPoint.Y);
var w = Math.Max(pos.X, this.currentImage.StartPoint.X) - x;
var h = Math.Max(pos.Y, this.currentImage.StartPoint.Y) - y;
var rect = new System.Windows.Shapes.Rectangle
{
Stroke = System.Windows.Media.Brushes.LightBlue,
StrokeThickness = 2
};
this.currentImage.RectSelectArea = rect;
this.currentImage.RectSelectArea.Width = w;
this.currentImage.RectSelectArea.Height = h;
Canvas.SetLeft(this.currentImage.RectSelectArea, x);
Canvas.SetTop(this.currentImage.RectSelectArea, y);
}
}
RelayCommand<MouseButtonEventArgs> mouseUpCommand;
public RelayCommand<MouseButtonEventArgs> MouseUpCommand
{
get
{
if (mouseUpCommand == null)
{
mouseUpCommand = new RelayCommand<MouseButtonEventArgs>(MouseUp);
}
return mouseUpCommand;
}
}
public void MouseUp(MouseButtonEventArgs e)
{
System.Windows.Controls.Image croppedImage = new System.Windows.Controls.Image();
croppedImage.Width = 100;
croppedImage.Margin = new Thickness(5);
this.currentImage.CropXPosition = (int)this.currentImage.StartPoint.X;
this.currentImage.CropYPosition = (int)this.currentImage.StartPoint.Y;
this.currentImage.CropWidth = (int)this.currentImage.RectSelectArea.Width;
this.currentImage.CropHeight = (int)this.currentImage.RectSelectArea.Height;
CroppedBitmap cb = new CroppedBitmap(
(BitmapSource)this.currentImage.ImagePath, new Int32Rect(
this.currentImage.CropXPosition, this.currentImage.CropYPosition, this.currentImage.CropWidth, this.currentImage.CropHeight));
croppedImage.Source = cb;
}
The MouseButtonEventToArgsToPointConverter:
class MouseButtonEventArgsToPointConverter : IEventArgsConverter
{
public object Convert(object value, object parameter)
{
var args = (MouseButtonEventArgs)value;
var element = (FrameworkElement)parameter;
var point = args.GetPosition(element);
return point;
}
}
I also followed this advice from a similar question if not same question, but the RelayCommand won't work as a type Point. How can I fix this? Or is my approach wrong? Really thankful for any kind of help or suggestions.
Upvotes: 0
Views: 1391
Reputation: 4679
You are converting the MouseButtonEventArgs
to a Point in the MouseButtonEventArgsToPointConverter
but the commands are expecting a MouseButtonEventArgs
parameter - hence the cast exception. You convert it to a Point
and then the Point
is passed to the RelayCommand<MouseButtonEventArgs>
, an attempt is then made to cast Point
to MouseButtonEventArgs
which it obviously cannot do. Do you want to pass the Point or the event args? If point then change the command to RelayCommand<Point>
, if event args then remove use of the converter
Either:
<cmd:EventToCommand Command="{Binding Mode=OneWay,
Path=MouseDownCommand}"
EventArgsConverter="{StaticResource MouseButtonEventArgsToPointConverter}"
EventArgsConverterParameter="{Binding ElementName=_image}"
PassEventArgsToCommand="True" />
public RelayCommand<Point> MouseDownCommand
{
get
{
...
}
}
Also in this case you need to change MouseDown to this:
public void MouseDown(Point p)
Or:
<cmd:EventToCommand Command="{Binding Mode=OneWay,
Path=MouseDownCommand}" PassEventArgsToCommand="True" />
public RelayCommand<MouseButtonEventArgs> MouseDownCommand
{
get
{
...
}
}
Upvotes: 1