使用MVVM绑定AvalonDock中浮动元素的大小和位置

时间:2014-05-28 07:19:51

标签: c# wpf mvvm avalondock

我正在尝试绑定Width中浮动(未停靠)文档的HeightAvalonDock属性。我正在使用MVVM模式 我想保存属性(连同对接状态和窗口的位置,如果未对接)并能够恢复它们。使用XmlLayoutSerializer不是一个选项,因为这需要对ViewModel中不允许的对接管理器的引用。

这是XAML代码:

<avalonDock:DockingManager DocumentsSource="{Binding Files}"
                           ActiveContent="{Binding ActiveDocument, Mode=TwoWay}">
    <avalonDock:DockingManager.LayoutItemContainerStyle>
        <Style TargetType="{x:Type avalonDock:LayoutDocumentItem}">
            <Setter Property="Title" Value="{Binding Model.Title}"/>
            <Setter Property="CanClose" Value="False" />
            <Setter Property="CanFloat" Value="True" />
        </Style>
    </avalonDock:DockingManager.LayoutItemContainerStyle>

    <avalonDock:LayoutRoot>
        <avalonDock:LayoutPanel>
            <avalonDock:LayoutDocumentPane>
            </avalonDock:LayoutDocumentPane>
        </avalonDock:LayoutPanel>
    </avalonDock:LayoutRoot>

ViewModel:

private ObservableCollection<PaneViewModel> m_readonyFiles;
public ObservableCollection<PaneViewModel> Files
{
    get { return m_readonyFiles ?? (m_readonyFiles = 
             new ObservableCollection<PaneViewModel>()); }
}

private PaneViewModel _activeDocument = null;
public PaneViewModel ActiveDocument
{
    get { return _activeDocument; }
    set
    {
        if (_activeDocument != value)
        {
            _activeDocument = value;

            RaisePropertyChanged("ActiveDocument");
        }
    }
}

我尝试以LayoutDocumentItem的样式设置绑定,但是setter永远不会被调用:

<Window.Resources>
    <Style TargetType="{x:Type avalonDock:LayoutDocumentItem}">
        <Setter Property="Width" Value="{Binding ActiveDocument.CurrentWidth, Mode=TwoWay}"></Setter>
        <Setter Property="Height" Value="{Binding ActiveDocument.CurrentHeigth, Mode=TwoWay}"></Setter>
    </Style>
</Window.Resources>

如何在不违反MVVM模式的情况下保存和恢复浮动文档的大小和位置?


解决方案更新&gt;&gt;&gt;

我终于通过@Sheridan在其答案中链接的一篇文章中的一个想法解决了我的问题。我创建了一个信使,用于处理我的ViewModel和View的CodeBehind之间的通信。在那里,我获得文档的位置和大小,并将它们发送回ViewModel。要恢复,我使用ILayoutUpdateStrategy并在函数AfterInsertDocument中恢复状态。

1 个答案:

答案 0 :(得分:2)

在WPF中,我们操纵数据元素而不是 UI元素。因此,只需保存相关的属性值,而不是尝试保存UI控件及其荒谬的属性。通常,执行此操作的最佳方法是声明包含所需属性类型和值的自定义类。

但是,在AvalonDock的情况下,DockingManager对象有一个方便的扩展函数来处理这个问题:

/// <summary>
/// Event raised when the window is about to close.
/// </summary>
private void Window_Closing(object sender, CancelEventArgs e)
{
    ...

    //
    // When the window is closing, save AvalonDock layout to a file.
    //
    avalonDockHost.DockingManager.SaveLayout(LayoutFileName);
}

...

/// <summary>
/// Event raised when AvalonDock has loaded.
/// </summary>
private void avalonDockHost_AvalonDockLoaded(object sender, EventArgs e)
{
    if (System.IO.File.Exists(LayoutFileName))
    {
        //
        // If there is already a saved layout file, restore AvalonDock layout from it.
        //
        avalonDockHost.DockingManager.RestoreLayout(LayoutFileName);
    }
    else
    {
        //
        // ... no previously saved layout exists, need to load default layout ...
        //
    }
}

这些示例来自代码项目的AvalonDock and MVVM页面,您可能会因其他原因而感兴趣。有关该主题的进一步帮助,请参阅代码项目的Loading/Saving AvalonDock Layouts at Start-up/Shut-Down页面,或CodePlex的AvalonDock部分的Save/Load Layout & ContentAvalonDock 2.0 getting started guide PART 2页面。