在 WPF 应用程序中实现 MVVM 模式、方法

Posted

技术标签:

【中文标题】在 WPF 应用程序中实现 MVVM 模式、方法【英文标题】:Implementing MVVM pattern in WPF application, methods 【发布时间】:2018-04-13 06:41:00 【问题描述】:

如何重构以下事件处理程序以适应 ViewModel?

private void imgSkipBack_MouseDown(object sender, MouseButtonEventArgs e)

    if (e.ChangedButton == MouseButton.Left)
    
        SetNewPlayerPosition(ViewModel.MovieElapsedTime.Subtract(Settings.SkipSeconds).TotalSeconds >= 0
            ? ViewModel.MovieElapsedTime.Subtract(Settings.SkipSeconds)
            : new TimeSpan(0));
    


private void SetNewPlayerPosition(TimeSpan newPosition)

    Player.Position = newPosition;
    AlignTimersWithSource(Player.Position);


private void AlignTimersWithSource(TimeSpan currentPosition)

    ViewModel.MovieLeftTime = Player.NaturalDuration.TimeSpan - currentPosition;
    ViewModel.MovieElapsedTime = currentPosition;

其中vm声明如下:

public class VideoPlayerViewModel : ViewModelBase

    private TimeSpan _movieElapsedTime = default(TimeSpan);
    public TimeSpan MovieElapsedTime
    
        get => _movieElapsedTime;
        set
        
            if (value != _movieElapsedTime)
            
                _movieElapsedTime = value;
                OnPropertyChanged();
            
        
    

    private TimeSpan _movieLeftTime = default(TimeSpan);
    public TimeSpan MovieLeftTime
    
        get => _movieLeftTime;
        set
        
            if (value != _movieLeftTime)
            
                _movieLeftTime = value;
                OnPropertyChanged();
            
        
    

我尝试过使用命令,但除了实际遵循 MVVM 模式之外,它们似乎没有任何好处,这个版本实际上只在 xaml 中添加了额外的代码,以允许我将 EventArgs 作为命令参数传递。

【问题讨论】:

@MickyD 很抱歉,如果听起来是这样,我只是在寻找重构此代码的方法。我决定让人们知道我为解决问题所做的努力。 @gldraphael 我可以看到那里的混乱,我已经改写了最后一句话。 看起来您正在尝试 MVVM,方法是采用属于代码隐藏中的特定于 UI 的逻辑,并将其塞进一个视图模型中,除了保留该代码隐藏之外,它绝对没有任何用处。那是一种反模式,最终可能会搞砸你。 您不会“将 [您的] 代码保留为空”。 MVVM != 没有代码隐藏。 UI 逻辑保留在 UI 中。业务逻辑保留在您的模型和视图模型中。您并不真正了解该模式的工作原理。如果你不花几个小时做更多的研究(并且可能买一本关于这个主题的书),你只会给自己带来更多的痛苦。 我建议在亚马逊上搜索书籍。按用户评论对结果进行排序。 【参考方案1】:

如何重构以下事件处理程序以适应 ViewModel?

当元素的MouseLeftButtonDown 事件引发时,您可以使用交互触发器来调用命令:

<Image ...>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseLeftButtonDown" >
            <i:InvokeCommandAction Command="Binding YourCommand" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Image>

您需要参考System.Windows.Interactivity。请参阅以下博客文章了解更多信息:https://blog.magnusmontin.net/2013/06/30/handling-events-in-an-mvvm-wpf-application/。

我尝试过使用命令,但除了实际遵循 MVVM 模式之外,它们似乎没有提供任何好处...

好处是您将应用程序逻辑(即单击元素时发生的情况)移动到它所属的视图模型中。

【讨论】:

感谢您的回答,能否举例说明该命令的外观? 请阅读博文。您只需在命令的 Execute 方法中调用您的 SetNewPlayerPosition 方法。 如何将我的MediaElement Player 移动到 ViewModel?因为我要访问这个控件的很多属性,所以我宁愿把它放在 vm 中 你可以实现一个接口:***.com/questions/10631748/… 我以前看过这篇文章,但我真的很感谢我的具体情况的一个例子,如果我要求太多,对不起。

以上是关于在 WPF 应用程序中实现 MVVM 模式、方法的主要内容,如果未能解决你的问题,请参考以下文章

WPF MVVM模式下实现ListView下拉显示更多内容

使用 MVVM 在 WPF 中创建新窗口的最佳方法

如何在 SwiftUI 中实现 MVVM 模式?视图不会重新渲染

遵循 MVVM 模式在 WPF 应用程序中处理导航的最佳方法是啥?

如何在Android MVVM架构中实现对话框选择选项

在 Flutter Native Android 代码中实现 MVVM 架构