我应该如何使用MVVM移动WPF窗口?

时间:2010-08-06 15:54:08

标签: wpf mvvm

这可能对MVVM模式有些过分,但对我来说这是新的,我很想知道它是否可行。

如果我附加到Window的MouseMove事件并执行DragMove,我可以移动无边框窗口。我可以通过MVVM中的其他方法实现这一点,还是应该接受将此代码添加到Window的代码隐藏中?

6 个答案:

答案 0 :(得分:3)

我个人认为使用MVVM的任何解决方案都不会使这个代码更好。此外,这通常与视图相关,并且与您正在显示的数据无关。

答案 1 :(得分:3)

这是纯UI逻辑,不属于ViewModel。你不想把它放在你的代码隐藏中的唯一原因是重复使用,这可以通过自定义的Window派生控件更好地解决。

答案 2 :(得分:2)

恕我直言,除非这是影响你的数据(又称模型)的东西,否则它是View代码,应该在View的代码隐藏中,而不是在模型中。

答案 3 :(得分:2)

我要回答你的问题。答案是肯定的。我正在使用Cinch来帮助我进行事件绑定和查看模型创建。该解决方案使用DragMove,但不是代码隐藏的一部分(我相信你在问这个问题)。

XAML中的事件绑定:

<Window 
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:cinchV2="clr-namespace:Cinch;assembly=Cinch.WPF"
    ...>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseLeftButtonDown">
            <cinchV2:EventToCommandTrigger Command="{Binding MouseLeftButtonDown}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Grid>
        ...
    </Grid>
</Window>

在ViewModel中:

[ExportViewModel("MainViewModel")]
[PartCreationPolicy(CreationPolicy.NonShared)]
internal sealed class MainViewModel : ViewModelBase
{
    public SimpleCommand<object, EventToCommandArgs> MouseLeftButtonDown { get; private set; }

    [ImportingConstructor]
    public MainViewModel(IUIVisualizerService uiVisualizerService)
    {
        ...
        MouseLeftButtonDown = new SimpleCommand<object, EventToCommandArgs>(OnMouseLeftButtonDown);
    }

    private static void OnMouseLeftButtonDown(EventToCommandArgs e)
    {
        ((Window)e.Sender).DragMove();
    }
}

相当简单吧?来自UI的任何事件都包含View作为发件人。所以,在这里,我们只需在ViewModel中的事件处理程序中调用视图上的方法。

我正在开发的项目不使用代码隐藏(即使在MVVM中不推荐使用它)。

答案 4 :(得分:2)

我知道我对这个问题有点迟了,但这就是我现在使用的一段时间,它就像一个魅力。

DashboardViewModel viewModel;
public DashboardView()
{
    InitializeComponent();
    viewModel = new DashboardViewModel();
    viewModel.RequestClose += (s, e) => Application.Current.Dispatcher.Invoke(this.Close);
    viewModel.RequestMinimize += (s, e) => Application.Current.Dispatcher.Invoke(() => { this.WindowState = WindowState.Minimized; });
    DataContext = viewModel;
}

和viewModel中的类似内容

#region Public Event Handlers
public event EventHandler<EventArgs> RequestClose;
public event EventHandler<EventArgs> RequestMinimize;
#endregion

使用ICommand界面...

#region ICommand Members
public ICommand CloseCommand { get; private set; }
public ICommand MinimizeCommand { get; private set; }
#endregion

配置命令...

private void SetupCommands()
{
    CloseCommand = new RelayCommand(CloseApplication);
    MinimizeCommand = new RelayCommand(MinimizeApplication);
}

这是RelayCommand类。

public class RelayCommand : ICommand
{
#region Private Readonly Properties
private readonly Action<object> executeCommand;
private readonly Predicate<object> canExecute;
#endregion

#region Constructors
public RelayCommand(Action<object> execute) : this(execute, null)
{

}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
    if (execute == null) 
        throw new ArgumentNullException("execute");
    this.executeCommand = execute; 
    this.canExecute = canExecute;
}
#endregion

#region Public ICommand Members
public bool CanExecute(object parameter)
{
    return canExecute == null ? true : canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
    executeCommand(parameter);
}
#endregion
}

一些示例方法......

private void MinimizeApplication(object obj)
{
    RequestMinimize(this, new EventArgs());
}
private void CloseApplication(object obj)
{
    RequestClose(this, new EventArgs());
}

希望这有帮助!

答案 5 :(得分:0)

我知道这是一个老问题。但是,我准备了另一个简单的实现。使用以下行为使窗口可移动:

public class WindowMoveBehavior : Behavior<Grid>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.MouseLeftButtonDown += AssociatedObject_MouseLeftButtonDown;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.MouseLeftButtonDown -= AssociatedObject_MouseLeftButtonDown;
        base.OnDetaching();
    }

    private void AssociatedObject_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        Window.GetWindow(AssociatedObject).DragMove();
    }
}

Xaml示例:

<Style x:Key="CustomWindowStyle" TargetType="{x:Type Window}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Window}">
                <Grid>
                    <i:Interaction.Behaviors>
                        <behaviors:WindowMoveBehavior/>
                    </i:Interaction.Behaviors>
     <!-- different controls and content -->
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>