MVVM关闭文档的方式,可以取消

本文关键字:取消 方式 文档 MVVM | 更新日期: 2023-09-27 18:34:44

我正在将Avalondock 2.x用于我的一个开源项目,如果关闭文档时文档很脏,您应该可以取消关闭。

我正在使用 Caliburn Micro 和 Coroutine,我能够解决它的唯一方法是使用 C.M 附加到事件

<i:EventTrigger EventName="DocumentClosing">
    <cal:ActionMessage MethodName="DocumentClosing">
        <cal:Parameter Value="$documentcontext" />
        <cal:Parameter Value="$eventArgs" />
    </cal:ActionMessage>
</i:EventTrigger>

事件参数具有取消属性。这个应用程序的问题在于它对 MVVM 不是很友好,我创建了一个小的辅助方法来像 Coroutinize 一样

public IEnumerable<IResult> Coroutinify(IEnumerable<IResult> results, System.Action cancelCallback)
{
    return results.Select(r =>
        {
            if (r is CancelResult)
                cancelCallback();
            return r;
        });
}

像这样使用

public IEnumerable<IResult> DocumentClosing(ScriptEditorViewModel document, DocumentClosingEventArgs e)
{
    return Result.Coroutinify(HandleScriptClosing(document), () => e.Cancel = true);
}

这有效,但它有点笨拙等,是否有一种更 MVVM 的方式来关闭具有取消功能的 Avalondock 中的文档?

编辑:源代码

https://github.com/AndersMalmgren/FreePIE/blob/master/FreePIE.GUI/Shells/MainShellView.xaml#L29

https://github.com/AndersMalmgren/FreePIE/blob/master/FreePIE.GUI/Shells/MainShellViewModel.cs#L110

https://github.com/AndersMalmgren/FreePIE/blob/master/FreePIE.GUI/Result/ResultFactory.cs#L49

MVVM关闭文档的方式,可以取消

我完成此操作的方法是绑定到 AvalonDock LayoutItem 的 CloseCommand 属性。关联此绑定时,它将覆盖关闭文档的默认行为("X"按钮,右键单击关闭/全部关闭(。然后,如果需要,您将全权负责删除(关闭(文档。

我设置它的方式是拥有一个包含DocumentVM的Observable集合的DocumentManagerVM。每个 DocumentVM 都有一个名为 RequestCloseCommand 的 ICommand,它可以通过从它拥有的 DocumentManagerVM 集合中删除自身来关闭文档。

具体来说,在我的 DocumentVM 视图模型中,有一个 ICommand(我正在使用 mvvmLight RelayCommand(来执行关闭逻辑:

public RelayCommand RequestCloseCommand { get; private set; }
void RequestClose()
{
    // if you want to prevent the document closing, just return from this function
    // otherwise, close it by removing it from the collection of DocumentVMs
    this.DocumentManagerVM.DocumentVMs.Remove(this);
}

在您的视图中,在 LayoutItemContainerStyle 或 LayoutItemContainerStyleSelector 中设置绑定。

<ad:DockingManager
    DataContext="{Binding DocumentManagerVM}"
    DocumentsSource="{Binding DocumentVMs}">
    <ad:DockingManager.LayoutItemContainerStyle>
        <Style TargetType="{x:Type ad:LayoutItem}">
            <Setter Property="Title" Value="{Binding Model.Header}"/>
            <Setter Property="CloseCommand" Value="{Binding Model.RequestCloseCommand}"/>
        </Style>
    </ad:DockingManager.LayoutItemContainerStyle>
</ad:DockingManager>

我在 DockingManger 中添加了一个依赖属性,它允许绑定到 Close 命令:

public static class DocumentClosingBehavior
{
    #region Dependecy Property
    private static readonly DependencyProperty DocumentClosingCommandProperty = DependencyProperty.RegisterAttached
                (
                    "DocumentClosingCommand",
                    typeof(ICommand),
                    typeof(DocumentClosingBehavior),
                    new PropertyMetadata(DocumentClosingCommandPropertyChangedCallBack)
                );
    #endregion
    #region Methods
    public static void SetDocumentClosingCommand(this UIElement inUIElement, ICommand inCommand)
    {
        inUIElement.SetValue(DocumentClosingCommandProperty, inCommand);
    }
    private static ICommand GetDocumentClosingCommand(UIElement inUIElement)
    {
        return (ICommand)inUIElement.GetValue(DocumentClosingCommandProperty);
    }
    #endregion
    #region CallBack Method
    private static void DocumentClosingCommandPropertyChangedCallBack(DependencyObject inDependencyObject, DependencyPropertyChangedEventArgs inEventArgs)
    {
        DockingManager uiElement = inDependencyObject as DockingManager;
        if (null == uiElement) return;
        uiElement.DocumentClosing += (sender, args) =>
        {
            GetDocumentClosingCommand(uiElement).Execute(args);
        };
    }
    #endregion
}

在 XAML 中:

<xcad:DockingManager vm:DocumentClosingBehavior.DocumentClosingCommand="{Binding DocumentCloseCommand}" Grid.Row="2" 
                       AllowMixedOrientation="True"
                       BorderBrush="Black"
                       BorderThickness="1"
                       Theme="{Binding ElementName=_themeCombo, Path=SelectedItem.Tag}"
                       DocumentsSource="{Binding Documents}"
                       ActiveContent="{Binding ActiveDocument, Mode=TwoWay, Converter={StaticResource ActiveDocumentConverter}}"
                       >

在我的 MainViewModel 中,我定义了一个 ICommand DocumentCloseCommand。