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
我完成此操作的方法是绑定到 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。