如何将TabControl.ContentTemplate中的MVVM鼠标位置转换为ViewModel?

时间:2017-12-22 18:28:10

标签: c# wpf mvvm mouse tabcontrol

我正在创建一个简单的图像编辑风格的应用程序,并且我第一次尝试使用MVVM。我们的想法是解析专有文本文件并在应用程序中的标签中直观地表示它们,以便在转换回文本之前可以使用绘画描边等进行更新。在弄清楚如何将鼠标定位到视图模型时,我发现Mark Green's solution效果很好;但是,如果我把它放在我的TabControl.ContentTemplate中,我就无法工作 - 如果我这样做,当我加载第一个文本文件(创建第一个标签)时,程序会毫不客气地崩溃。这是代码的相关部分(请参阅ViewModel中使用的代码的链接):

<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>

正如您在代码中的评论中所看到的,我对交互行为的放置似乎正在破坏应用程序。由于异常发生在外部代码中,我无法弄清楚究竟出了什么问题,但我怀疑它与模板内部的代码有关(如果我错了请纠正我!)。

我的问题是:如何在模板中使用交互行为(以及后来的触发器 - 我也想要鼠标按钮事件),或者我是以错误的方式进行此操作?是否有更好的解决方案将鼠标位置(相对于图像)提供给ViewModel?

非常感谢您提供的任何帮助!

更新 根据STrenat的建议,我更新了MouseBehavior类以使用UIElement而不是Panel:

public class MouseBehaviour : System.Windows.Interactivity.Behavior<UIElement>
{
    // Rest of code from Mark Green's solution linked in original post
}

要在主窗口中访问鼠标位置值(而不是在ItemTemplate内部),我更新了XAML中的绑定(现在显示输出文本块)以指向主视图模型中的属性(没有相对属性)引用你必须在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>

其余部分与上面引用的解决方案中指定的一样。希望能帮助其他人遇到这个问题!

0 个答案:

没有答案