如何在WPF中将正常的ViewModel添加到AvalonDock LayoutDocumentPane?

时间:2015-02-24 15:42:44

标签: c# wpf mvvm docking avalondock

据我所知,AvalonDock有两种方法可以添加ViewModels。 AnchorablesSource和DocumentsSource属性。我只是希望能够以FileViewModel在LayoutDocumentPane中的方式记录我当前的ViewModel而不从FileViewModel派生。问题是,如果您不从FileViewModel派生,则窗口会丢失其所有标签。此外,如果您使用AnchorableSource而不是DocumentSource,当您添加新窗口时,它将添加到主窗口的右侧,而不是作为文档窗格的选项卡。有谁知道如何实现这个理想的结果?

源代码参考

http://avalondock.codeplex.com/

这是AvalonDock测试应用程序附带的FileViewModel

namespace AvalonDock.MVVMTestApp
{
class FileViewModel : PaneViewModel
{
    static ImageSourceConverter ISC = new ImageSourceConverter();
    public FileViewModel(string filePath)
    {
        FilePath = filePath;
        Title = FileName;

        //Set the icon only for open documents (just a test)
        IconSource = ISC.ConvertFromInvariantString(@"pack://application:,,/Images/document.png") as ImageSource;
    }

    public FileViewModel()
    {
        IsDirty = true;
        Title = FileName;
    }

    #region FilePath
    private string _filePath = null;
    public string FilePath
    {
        get { return _filePath; }
        set
        {
            if (_filePath != value)
            {
                _filePath = value;
                RaisePropertyChanged("FilePath");
                RaisePropertyChanged("FileName");
                RaisePropertyChanged("Title");

                if (File.Exists(_filePath))
                {
                    _textContent = File.ReadAllText(_filePath);
                    ContentId = _filePath;
                }
            }
        }
    }
    #endregion


    public string FileName
    {
        get 
        {
            if (FilePath == null)
                return "Noname" + (IsDirty ? "*" : "");

            return System.IO.Path.GetFileName(FilePath) + (IsDirty ? "*" : ""); 
        }
    }



    #region TextContent

    private string _textContent = string.Empty;
    public string TextContent
    {
        get { return _textContent; }
        set
        {
            if (_textContent != value)
            {
                _textContent = value;
                RaisePropertyChanged("TextContent");
                IsDirty = true;
            }
        }
    }

    #endregion

    #region IsDirty

    private bool _isDirty = false;
    public bool IsDirty
    {
        get { return _isDirty; }
        set
        {
            if (_isDirty != value)
            {
                _isDirty = value;
                RaisePropertyChanged("IsDirty");
                RaisePropertyChanged("FileName");
            }
        }
    }

    #endregion

    #region SaveCommand
    RelayCommand _saveCommand = null;
    public ICommand SaveCommand
    {
        get
        {
            if (_saveCommand == null)
            {
                _saveCommand = new RelayCommand((p) => OnSave(p), (p) => CanSave(p));
            }

            return _saveCommand;
        }
    }

    private bool CanSave(object parameter)
    {
        return IsDirty;
    }

    private void OnSave(object parameter)
    {
        Workspace.This.Save(this, false);
    }

    #endregion

    #region SaveAsCommand
    RelayCommand _saveAsCommand = null;
    public ICommand SaveAsCommand
    {
        get
        {
            if (_saveAsCommand == null)
            {
                _saveAsCommand = new RelayCommand((p) => OnSaveAs(p), (p) => CanSaveAs(p));
            }

            return _saveAsCommand;
        }
    }

    private bool CanSaveAs(object parameter)
    {
        return IsDirty;
    }

    private void OnSaveAs(object parameter)
    {
        Workspace.This.Save(this, true);
    }

    #endregion

    #region CloseCommand
    RelayCommand _closeCommand = null;
    public ICommand CloseCommand
    {
        get
        {
            if (_closeCommand == null)
            {
                _closeCommand = new RelayCommand((p) => OnClose(), (p) => CanClose());
            }

            return _closeCommand;
        }
    }

    private bool CanClose()
    {
        return true;
    }

    private void OnClose()
    {
        Workspace.This.Close(this);
    }
    #endregion

}

}

以下是来自测试应用程序的主窗口xaml

<Window x:Class="AvalonDock.MVVMTestApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:avalonDock="http://schemas.xceed.com/wpf/xaml/avalondock"
    xmlns:shell="clr-namespace:Microsoft.Windows.Shell;assembly=AvalonDock"
    xmlns:local="clr-namespace:AvalonDock.MVVMTestApp"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:sysWindows="clr-namespace:System.Windows;assembly=PresentationCore"
    x:Name="mainWindow"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <local:ActiveDocumentConverter x:Key="ActiveDocumentConverter"/>
    <avalonDock:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Menu>
        <MenuItem Header="File">
            <MenuItem Header="New" Command="{Binding NewCommand}"/>
            <MenuItem Header="Open" Command="{Binding OpenCommand}"/>
            <Separator/>
            <MenuItem Header="Save" Command="{Binding ActiveDocument.SaveCommand}"/>
            <MenuItem Header="Save As..." Command="{Binding ActiveDocument.SaveAsCommand}"/>
            <Separator/>
            <MenuItem Header="Close" Command="{Binding ActiveDocument.CloseCommand}"/>
        </MenuItem>
        <MenuItem Header="Tools">
            <MenuItem Header="Properties" IsChecked="{Binding FileStats.IsVisible, Mode=TwoWay}" IsCheckable="True"/>
        </MenuItem>
        <MenuItem Header="Layout">
            <MenuItem Header="Load" Command="{Binding LoadLayoutCommand, ElementName=mainWindow}"/>
            <MenuItem Header="Save" Command="{Binding SaveLayoutCommand, ElementName=mainWindow}"/>
            <MenuItem Header="Dump to Console" Click="OnDumpToConsole"/>

        </MenuItem>
    </Menu><!--AnchorablesSource="{Binding Tools}" DocumentsSource="{Binding Files}"-->
    <avalonDock:DockingManager x:Name="dockManager" 
                               AnchorablesSource="{Binding Tools}" 
                               DocumentsSource="{Binding Files}"
                               ActiveContent="{Binding ActiveDocument, Mode=TwoWay, Converter={StaticResource ActiveDocumentConverter}}"
                               Grid.Row="1">
        <!--<avalonDock:DockingManager.Theme>
            <avalonDock:AeroTheme/>
        </avalonDock:DockingManager.Theme>-->
        <avalonDock:DockingManager.LayoutItemTemplateSelector>
            <local:PanesTemplateSelector>
                <local:PanesTemplateSelector.FileViewTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding TextContent, UpdateSourceTrigger=PropertyChanged}"/>
                    </DataTemplate>
                </local:PanesTemplateSelector.FileViewTemplate>
                <local:PanesTemplateSelector.FileStatsViewTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Vertical">
                            <TextBlock Text="{Binding FileSize}"/>
                            <TextBlock Text="{Binding LastModified}"/>
                            <TextBox Text="test"/>
                        </StackPanel>
                    </DataTemplate>
                </local:PanesTemplateSelector.FileStatsViewTemplate>
            </local:PanesTemplateSelector>
        </avalonDock:DockingManager.LayoutItemTemplateSelector>




        <avalonDock:DockingManager.LayoutItemContainerStyleSelector>
            <local:PanesStyleSelector>
                <local:PanesStyleSelector.ToolStyle>
                    <Style TargetType="{x:Type avalonDock:LayoutAnchorableItem}">
                        <!--<Setter Property="Title" Value="{Binding Model.Title}"/>-->
                        <Setter Property="IconSource" Value="{Binding Model.IconSource}"/>
                        <Setter Property="Visibility" Value="{Binding Model.IsVisible, Mode=TwoWay, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter={x:Static Visibility.Hidden}}"/>
                        <Setter Property="ContentId" Value="{Binding Model.ContentId}"/>
                        <Setter Property="IsSelected" Value="{Binding Model.IsSelected, Mode=TwoWay}"/>
                        <Setter Property="IsActive" Value="{Binding Model.IsActive, Mode=TwoWay}"/>
                    </Style>
                </local:PanesStyleSelector.ToolStyle>
                <local:PanesStyleSelector.FileStyle>
                    <Style TargetType="{x:Type avalonDock:LayoutItem}">
                        <Setter Property="Title" Value="{Binding Model.Title}"/>
                        <!--<Setter Property="ToolTip" Value="{Binding Model.FilePath}"/>
                        <Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}"/>
                        <Setter Property="IconSource" Value="{Binding Model.IconSource}"/>
                        <Setter Property="ContentId" Value="{Binding Model.ContentId}"/>-->
                    </Style>
                </local:PanesStyleSelector.FileStyle>
            </local:PanesStyleSelector>
        </avalonDock:DockingManager.LayoutItemContainerStyleSelector>


        <avalonDock:DockingManager.LayoutUpdateStrategy>
            <local:LayoutInitializer/>
        </avalonDock:DockingManager.LayoutUpdateStrategy>

        <avalonDock:LayoutRoot>
            <avalonDock:LayoutPanel Orientation="Vertical">
                <avalonDock:LayoutDocumentPane/>
                <avalonDock:LayoutAnchorablePane Name="ToolsPane" DockHeight="150">
                </avalonDock:LayoutAnchorablePane>
            </avalonDock:LayoutPanel>
        </avalonDock:LayoutRoot>


    </avalonDock:DockingManager>
</Grid>

这是主窗口的ViewModel,我对它进行了编辑,它与这里发布的xaml不匹配,因为它是原始形式。我只是尝试用我自己的DockingViewModel替换FileViewModel。

    class Workspace : ViewModelBase
{
    protected Workspace()
    {

    }

    static Workspace _this = new Workspace();

    public static Workspace This
    {
        get { return _this; }
    }


    ObservableCollection<FileViewModel> _files = new ObservableCollection<FileViewModel>();
    ReadOnlyObservableCollection<FileViewModel> _readonyFiles = null;
    public ReadOnlyObservableCollection<FileViewModel> Files
    {
        get
        {
            if (_readonyFiles == null)
                _readonyFiles = new ReadOnlyObservableCollection<FileViewModel>(_files);

            return _readonyFiles;
        }
    }

    //ToolViewModel[] _tools = null;

    //public IEnumerable<ToolViewModel> Tools
    //{
    //    get
    //    {
    //        if (_tools == null)
    //            _tools = new ToolViewModel[2];
    //        return _tools;
    //    }
    //}

    ObservableCollection<DockingViewModel> _tools = new ObservableCollection<DockingViewModel>();
    ReadOnlyObservableCollection<DockingViewModel> _readonyTools = null;
    public ReadOnlyObservableCollection<DockingViewModel> Tools
    {
        get
        {
            if (_readonyTools == null)
                _readonyTools = new ReadOnlyObservableCollection<DockingViewModel>(_tools);

            return _readonyTools;
        }
    }


    FileStatsViewModel _fileStats = null;
    public FileStatsViewModel FileStats
    {
        get
        {
            if (_fileStats == null)
                _fileStats = new FileStatsViewModel();

            return _fileStats;
        }
    }

    #region OpenCommand
    RelayCommand _openCommand = null;
    public ICommand OpenCommand
    {
        get
        {
            if (_openCommand == null)
            {
                _openCommand = new RelayCommand((p) => OnOpen(p), (p) => CanOpen(p));
            }

            return _openCommand;
        }
    }

    private bool CanOpen(object parameter)
    {
        return true;
    }

    private void OnOpen(object parameter)
    {
        //var dlg = new OpenFileDialog();
        //if (dlg.ShowDialog().GetValueOrDefault())
        //{
        //    var fileViewModel = Open(dlg.FileName);
        //    ActiveDocument = fileViewModel;
        //}
    }

    public FileViewModel Open(string filepath)
    {
        var fileViewModel = _files.FirstOrDefault(fm => fm.FilePath == filepath);
        if (fileViewModel != null)
            return fileViewModel;

        fileViewModel = new FileViewModel(filepath);
        _files.Add(fileViewModel);
        return fileViewModel;
    }

    #endregion

    #region NewCommand
    RelayCommand _newCommand = null;
    public ICommand NewCommand
    {
        get
        {
            if (_newCommand == null)
            {
                _newCommand = new RelayCommand((p) => OnNew(p), (p) => CanNew(p));
            }

            return _newCommand;
        }
    }

    private bool CanNew(object parameter)
    {
        return true;
    }

    private void OnNew(object parameter)
    {
        _tools.Add(new DockingViewModel("Hulk"));
        //_files.Add(new FileViewModel());
        //ActiveDocument = _files.Last();
        ActiveDocument = _tools.Last();
    }

    #endregion

    #region ActiveDocument

    private DockingViewModel _activeDocument = null;
    public DockingViewModel ActiveDocument
    {
        get { return _activeDocument; }
        set
        {
            if (_activeDocument != value)
            {
                _activeDocument = value;
                RaisePropertyChanged("ActiveDocument");
                if (ActiveDocumentChanged != null)
                    ActiveDocumentChanged(this, EventArgs.Empty);
            }
        }
    }

    public event EventHandler ActiveDocumentChanged;

    #endregion


    internal void Close(FileViewModel fileToClose)
    {
        if (fileToClose.IsDirty)
        {
            var res = MessageBox.Show(string.Format("Save changes for file '{0}'?", fileToClose.FileName), "AvalonDock Test App", MessageBoxButton.YesNoCancel);
            if (res == MessageBoxResult.Cancel)
                return;
            if (res == MessageBoxResult.Yes)
            {
                Save(fileToClose);
            }
        }

        _files.Remove(fileToClose);
    }

    internal void Save(FileViewModel fileToSave, bool saveAsFlag = false)
    {
        if (fileToSave.FilePath == null || saveAsFlag)
        {
            var dlg = new SaveFileDialog();
            if (dlg.ShowDialog().GetValueOrDefault())
                fileToSave.FilePath = dlg.SafeFileName;
        }

        File.WriteAllText(fileToSave.FilePath, fileToSave.TextContent);
        ActiveDocument.IsDirty = false;
    }



}

0 个答案:

没有答案