AvalonDock2.0をアプリケーションに統合しました。ドキュメントとアンカー可能なソースをビューモデルにバインドしました。これらは、DataTemplate
sを介して適切なユーザーコントロールでレンダリングされます。
を使用してレイアウトをロードおよび保存できますXmlLayoutSerializer
。事前定義されたレイアウトをオンデマンドでロードすることをサポートする必要があります(Button
sおよびICommand
sを介して)。それもうまくいきます。
私が作業できないのDockingManager
は、ビューモデルとそのビュー(ユーザーコントロール)の読み込みが完了すると、シリアル化されたレイアウトを自動的に読み込むことです。
レイアウトを読み込んでみましたDockingManager.DataContextChanged
が、非表示のセクションにドキュメントが読み込まれ、表示されているセクションにドキュメントが重複しているため、起動が早すぎると思います。レンダリングされたペインはロードされたレイアウトを反映せず、レイアウトが再度保存されると、重複が非表示のセクションに蓄積されます。
<ad:DockingManager Name="DockingManager"
DataContext="{Binding Project}"
DataContextChanged="DockingManager_OnDataContextChanged"
ActiveContent="{Binding Active}"
AnchorablesSource="{Binding Anchorables}"
DocumentsSource="{Binding Documents}">
<ad:DockingManager.Theme>
<ad:AeroTheme/>
</ad:DockingManager.Theme>
<ad:DockingManager.LayoutItemTemplateSelector>
<views:PanesTemplateSelector>
<views:PanesTemplateSelector.ChartTemplate>
<DataTemplate>
<views:Chart/>
</DataTemplate>
</views:PanesTemplateSelector.ChartTemplate>
<views:PanesTemplateSelector.WorkspaceTemplate>
<DataTemplate>
<Views:Workspace/>
</DataTemplate>
</views:PanesTemplateSelector.WorkspaceTemplate>
...
</views:PanesTemplateSelector>
</ad:DockingManager.LayoutItemTemplateSelector>
<ad:DockingManager.LayoutItemContainerStyle>
<Style TargetType="{x:Type ad:LayoutItem}">
<Setter Property="Title" Value="{Binding Model.DisplayText}"/>
<Setter Property="ContentId" Value="{Binding Model.ContentId}"/>
</Style>
</ad:DockingManager.LayoutItemContainerStyle>
<ad:LayoutRoot>
<!--<ad:LayoutPanel>
<ad:LayoutDocumentPane/>
<ad:LayoutAnchorablePane/>
</ad:LayoutPanel>-->
</ad:LayoutRoot>
</ad:DockingManager>
...そしてコードビハインド..。
private void SaveLayout() {
if (this.DataContext == null)
return;
var xmlLayoutSerializer = new XmlLayoutSerializer(this.DockingManager);
var stringBuilder = new StringBuilder();
using (var textWriter = new StringWriter(stringBuilder))
xmlLayoutSerializer.Serialize(textWriter);
var serialized = stringBuilder.ToString();
(this.DataContext as dynamic).XmlSerializedAndEscapedLayout = HttpUtility.HtmlEncode(serialized);
}
private void LoadLayout()
{
if (DataContext == null)
return;
var encoded = (DataContext as dynamic).XmlSerializedAndEscapedLayout;
var window = Window.GetWindow(this);
window.Closing += (sender, args) => SaveLayout();
if (String.IsNullOrWhiteSpace(encoded))
return;
var serialized = HttpUtility.HtmlDecode(encoded);
var xmlLayoutSerializer = new XmlLayoutSerializer(DockingManager);
using (var stringReader = new StringReader(serialized))
xmlLayoutSerializer.Deserialize(stringReader);
}
private void DockingManager_OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != null) // A type check here would be best, I know.
LoadLayout();
}
...そしてビューモデル..。
public class ProjectViewModel
{
public IModel Model { get; private set; }
public String SerializedLayout { get; set; }
public ViewModelBase Active { get; set; }
private readonly ObservableCollection<ViewModelBase> documents;
public ReadOnlyObservableCollection<ViewModelBase> Documents { get; private set; }
private readonly ObservableCollection<ViewModelBase> anchorables;
public ReadOnlyObservableCollection<ViewModelBase> Anchorables { get; private set; }
public ProjectViewModel(String filePath, String serializedLayout)
{
SerializedLayout = serializedLayout;
using (var fileStream = new FileStream(filePath, FileMode.Open))
{
IModelRepository modelRepository = Ioc.DependencyInjectionContainer.DefaultContainer.Resolve<IModelRepository>();
Model = modelRepository.Load(fileStream);
}
documents = new ObservableCollection<ViewModelBase>();
anchorables = new ObservableCollection<ViewModelBase>();
documents.Add(new Workspace());
anchorables.Add(new RiskLimitsViewModel(Model.RiskLimits));
...
Documents = new ReadOnlyObservableCollection<ViewModelBase>(documents);
Anchorables = new ReadOnlyObservableCollection<ViewModelBase>(anchorables);
}
}
任意の洞察をいただければ幸いです。ありがとう!