I am creating a simple image editing-style app and am attempting to use MVVM for the first time. The idea is to parse proprietary text files and represent them visually in tabs within the app so they can be updated with paint strokes and the like before being converted back to text. In figuring out how to get mouse position to the view model, I found Mark Green's solution works well; however, I can't get it to work if I place it inside my TabControl.ContentTemplate - if I do so, the program crashes unceremoniously when I load the first text file (which creates the first tab). Here's the relevant section of code (see link for the code used in the ViewModels):
<Grid>
<!--If I stick the Interaction behavior here it works, but I get mouse position relative to entire grid-->
<TabControl ItemsSource="{Binding Maps}" SelectedIndex='{Binding TabIndex}'>
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<Image x:Name="imgMap" Source='{Binding Content}'>
<i:Interaction.Behaviors><!--Putting it here causes an unhandled exception-->
<local:MouseBehaviour MouseX="{Binding PanelX, Mode=OneWayToSource}"
MouseY="{Binding PanelY, Mode=OneWayToSource}" />
</i:Interaction.Behaviors>
</Image>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
As you can see from my comments in the code, my placement of the interaction behavior seems to be what is breaking the app. Since the exception occurs in external code, I can't figure out exactly what is wrong but I suspect it has something to do with the code being inside a template (please correct me if I am wrong!).
My question is this: how do I get interaction behaviors (and later triggers - I will want mouse button events as well) working within the template, or am I going about this the wrong way? Is there a better solution to get mouse position (relative to the image) to the ViewModel?
Many thanks in advance for any help offered!
UPDATE Per STrenat's suggestion, I updated the MouseBehavior class to use UIElement instead of Panel:
public class MouseBehaviour : System.Windows.Interactivity.Behavior<UIElement>
{
// Rest of code from Mark Green's solution linked in original post
}
To get access to the mouse position values in the main window (instead of inside the ItemTemplate), I updated my bindings in the XAML (with output text blocks now shown) to point to properties in the main viewmodel (without the relative reference you have to have the properties inside the TabItem):
<StackPanel>
<TextBlock Text="{Binding PanelX, StringFormat='X={0:0}, '}" />
<TextBlock Text="{Binding PanelY, StringFormat='Y={0:0}'}" />
<TabControl ItemsSource="{Binding Maps}"
SelectedIndex='{Binding TabIndex}'>
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<Image x:Name="imgMap"
Source='{Binding Content}'>
<i:Interaction.Behaviors>
<local:MouseBehaviour MouseX="{Binding DataContext.PanelX, RelativeSource={RelativeSource AncestorType={x:Type Window}}, Mode=OneWayToSource}"
MouseY="{Binding DataContext.PanelY, RelativeSource={RelativeSource AncestorType={x:Type Window}}, Mode=OneWayToSource}" />
</i:Interaction.Behaviors>
</Image>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</StackPanel>
The rest is as specified in the solution referenced above. Hope that helps anybody else running into this problem!