代码之家  ›  专栏  ›  技术社区  ›  gr1d3r

MVVM-从视图模型关闭窗口

  •  3
  • gr1d3r  · 技术社区  · 7 年前

    在我的应用程序中,我使用prism并尝试实现以下概念:

    有一个通信窗口,可以有两个可能的用户控件。我有窗口和用户控件的ViewModels。 在每个用户控件中,我都有一些按钮。对于一些按钮,我需要在ViewModel中执行一些逻辑,当逻辑完成时,关闭父窗口。 我尝试将parant窗口作为命令参数发送,如下所示:

    CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"
    

    在viewModel中,使用以下代码关闭窗口:

    // Create the command
    OpenChannelCommand = new RelayCommand(OpenChannel, IsValidFields);
    ...
    private void OpenChannel()
    {
      // do some logic...
      CloseWindow();
    }
    private GalaSoft.MvvmLight.Command.RelayCommand<object> _closeCommand;
    private GalaSoft.MvvmLight.Command.RelayCommand<object> CloseWindow()
    {
        _closeCommand = new GalaSoft.MvvmLight.Command.RelayCommand<object>((o) => ((Window)o).Close(), (o) => true);
        return _closeCommand;
    }
    

    但窗户仍然没有关上。

    编辑:

    用户控件XAML代码为:

    <Button Content="Open Channel" Command="{Binding OpenChannelCommand}" 
                    CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/>
    

    用户控件ViewModel代码为:

    public RelayCommand OpenChannelCommand { get; set; } 
    ctor() 
    {
       OpenChannelCommand = new RelayCommand(OpenChannel, IsValidFields);
    }     
    private void OpenChannel() 
    {    
       // logic 
       CloseWindow(); 
    }
    private GalaSoft.MvvmLight.Command.RelayCommand<object> CloseWindow()
    {
        _closeCommand = new GalaSoft.MvvmLight.Command.RelayCommand<object>((o) => ((Window)o).Close(), (o) => true);
        return _closeCommand;
     }
    

    这是我目前尝试的完整实现。 将断点设置为CloseWindow方法时,它会在视图模式初始化时命中,在按钮中再次调用断点后,单击命令不会执行任何操作。

    1 回复  |  直到 7 年前
        1
  •  2
  •   Anton Tykhyy    7 年前

    关闭窗口是视图的责任,视图模型应该对此一无所知。难怪你会纠结在一起。如果在“按钮逻辑”运行时不需要窗口停留在屏幕上,那么只需使用 CompositeCommand 从Prism(我不太喜欢它,因为它使用代码隐藏,但没关系)或等效工具将两个命令绑定到按钮。另一方面,如果需要在“按钮逻辑”运行时保持窗口在屏幕上,例如显示进度,并且如果视图模型反映了这一点,则可以添加 bool IsButtonLogicComplete 属性到视图模型(不要忘记 INotifyPropertyChanged )并通过以下附加属性/行为将窗口的“关闭”状态绑定到此属性:

    public static class AttachedProperties
    {
        // in Visual Studio, the `propa` snippet inserts the boilerplate
        public static DependencyProperty ForceCloseProperty =
            DependencyProperty.RegisterAttached ("ForceClose",
            typeof (bool), typeof (AttachedProperties), new UIPropertyMetadata (false, (d, e) =>
            {
                var w  = d as Window ;
                if (w != null && (bool) e.NewValue)
                {
                    w.DialogResult = true ;
                    w.Close () ;
                }
            })) ;
    
        public static bool GetForceClose (DependencyObject obj)
        {
            return (bool) obj.GetValue (ForceCloseProperty) ;
        }
    
        public static void SetForceClose (DependencyObject obj, bool value)
        {
            obj.SetValue (ForceCloseProperty, value) ;
        }
    }
    
    <!-- in .xaml -->
    <Window
      xmlns:local="clr-namespace:YourNamespace"
      local:AttachedProperties.ForceClose="{Binding IsButtonLogicComplete}" ...
    

    这将使您的视图和视图模型关注点保持良好的分离。