【发布时间】:2020-07-19 18:12:48
【问题描述】:
我是 MVVM 的新手,我目前正在尝试将拖放功能添加到我的应用程序中。问题是我已经在代码隐藏中开发了接口,但我现在正尝试将代码重新写入 MVVM,因为我只是在项目的开始阶段。
这里是上下文:用户将能够将框(ToggleButton,但它可能会更改)添加到网格,有点像棋盘。下面是我正在处理的视图模型:
<Page.Resources>
<Style TargetType="{x:Type local:AirportEditionPage}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Page}">
<!-- The page content-->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding ToolKitWidth, FallbackValue=50}" />
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="{Binding RightPanelWidth, FallbackValue=400}"/>
</Grid.ColumnDefinitions>
<!-- The airport grid where Steps and Links are displayed -->
<ScrollViewer Grid.ColumnSpan="4" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Viewbox Height="{Binding AirportGridHeight}" Width="{Binding AirportGridWidth}" RenderOptions.BitmapScalingMode="HighQuality">
<ItemsControl x:Name="ChessBoard" ItemsSource="{Binding Items}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Width="{Binding CardQuantityRow}" Height="{Binding CardQuantityColumn}" Background="{StaticResource AirportGridBackground}"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Width="1" Height="1">
<ToggleButton Style="{StaticResource StepCardContentStyle}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding Pos.X}"/>
<Setter Property="Canvas.Top" Value="{Binding Pos.Y}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Viewbox>
</ScrollViewer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
项目基本上来自具有名称、图标和位置(点)的类(INotifiedPropertyChanged 的子级)。
现在,我试图让用户能够将框 (ToggleButton) 拖放到他/她想要的任何地方。但是,我对命令、附加属性等完全迷失了。我整天都在学习教程并尝试拖放解决方案,但由于知识贫乏,我不知道如何将所有这些应用到我的代码中。
在我的代码隐藏版本中,这很容易。当左键单击按钮时,我对网格的一个变量说“嘿,我正在被拖放”。当用户移动时,我更改了 Item 坐标,当用户松开左键(左键向上)时,dragdrop_object 变量再次变为 null。
在 MVVM 的框架中,我完全迷失了。你能给我一些曲目来帮助我度过难关吗?我本来打算放弃 MVVM 很多时间,但我知道最好跟上,即使每个小功能都需要几个小时才能实现(它应该随着时间的推移而减少......)。
如果您需要更多详细信息来回答我的问题,请不要犹豫。
【问题讨论】:
-
MVVM 基本上意味着将视图与模型分离并通过视图模型连接它们。此拖放看起来像您提到的由 XAML 文件的代码隐藏管理的视图,这就是 MVVM。如果拖放应该影响模型,则视图(XAML+代码隐藏)可以访问视图模型。因此,在代码隐藏中获取视图模型并进行更改。
-
感谢您的回复 Sorush !因此,如果我理解正确,即使它与我的模型(这里是我的项目)交互,在代码隐藏中制作它也不反对 MVVM。当我们开始在 MVVM 世界中区分什么可以在代码隐藏中实现和什么不能实现时,这并不容易。此外,我阅读了有关在 ViewModel 中进行拖放的文章,所以这可能会让我很困惑。
-
是的,XAML 和代码隐藏都是视图。有些东西使用代码隐藏更容易,比如复杂的视图逻辑,而有些东西使用 XAML 更容易,比如将视图元素绑定到视图模型属性。我强调视图只知道视图模型(而不是模型)。 View-model 只知道模型。该模型对其他人一无所知。基本上,模型是可移植的代码,您可以在其他地方使用它,例如在 Web 应用程序中。为了区别,将您的应用程序编写在执行所有逻辑的控制台应用程序中,创建用户期望看到的视图,并将它们与视图模型连接。
-
再次感谢您提供所有这些详细信息。它对我有很大帮助。问题是我已经在控制台应用程序中研究了一个巨大的算法。我确实知道在连接两个应用程序之前构建界面,我有点迷茫,但我开始看得更清楚了。最初,我还使用完整的代码隐藏(0 绑定)创建了接口(其中很大一部分),每个都运行良好,但我发现 MVVM 是一个更好的架构。我现在正试图将代码迁移到这种架构,但很痛苦。我会尽我所能,并牢记您的宝贵建议。
-
一般来说MVVM不是代码隐藏,而是业务逻辑和视图的分离。在 C#(或代码隐藏)中实现某些逻辑并没有错。处理 UI 事件是一种需要一些 C# 的方案,但无法使用
EventTrigger处理它们。 Patterns - WPF Apps With The Model-View-ViewModel Design Pattern。您不必将ItemsControl包装成ViewBox。