我有一个CustomControl和该控件的视图模型列表。使用ItemsControl我可以动态地为每个视图模型创建一个控件。现在我使用AvalonDock,我想为每个生成的UserControl添加一个DockableContent。如何动态完成?
答案 0 :(得分:2)
您希望将ViewModel集合绑定到停靠管理器的DocumentSource,并设置模板以绑定到title等属性,如下所示:
<dock:DockingManager DocumentsSource="{Binding Documents}" >
<dock:DockingManager.LayoutItemContainerStyle>
<Style TargetType="{x:Type dockctrl:LayoutItem}">
<Setter Property="Title" Value="{Binding Model.Title}" />
<Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}" />
<Setter Property="CanClose" Value="{Binding Model.CanClose}" />
</Style>
</dock:DockingManager.LayoutItemContainerStyle>
</dock:DockingManager>
并使用以下内容动态添加内容:
Documents.Add(MyNewlyCreatedViewModel)
编辑:使用静态窗格时,事情变得更加复杂。您必须使用模板选择器为普通/静态窗格选择正确的模板。 MVVM AvalonDock样本非常好。以下是我实现它的方法(工具是静态的):
<avalonDock:DockingManager
AnchorablesSource="{Binding Tools}"
DocumentsSource="{Binding Documents}"
AllowMixedOrientation="True" >
<avalonDock:DockingManager.Theme>
<avalonDock:MetroTheme />
</avalonDock:DockingManager.Theme>
<avalonDock:DockingManager.LayoutUpdateStrategy>
<helpers:LayoutUpdateStrategy />
</avalonDock:DockingManager.LayoutUpdateStrategy>
<avalonDock:DockingManager.LayoutItemContainerStyleSelector>
<helpers:AutobinderLayoutSelector>
<helpers:AutobinderLayoutSelector.DocumentStyle>
<Style TargetType="{x:Type avalonDock:LayoutItem}">
<Setter Property="Title" Value="{Binding Model.Title}" />
</Style>
</helpers:AutobinderLayoutSelector.DocumentStyle>
<helpers:AutobinderLayoutSelector.ToolStyle>
<Style TargetType="{x:Type avalonDock:LayoutItem}">
<Setter Property="Title" Value="{Binding Model.Title}" />
<Setter Property="IconSource" Value="{Binding Model.IconSource}"/>
</Style>
</helpers:AutobinderLayoutSelector.ToolStyle>
</helpers:AutobinderLayoutSelector>
</avalonDock:DockingManager.LayoutItemContainerStyleSelector>
<avalonDock:DockingManager.LayoutItemTemplateSelector>
<helpers:AutobinderTemplateSelector>
<helpers:AutobinderTemplateSelector.DocumentTemplate>
<DataTemplate>
<ContentControl cal:View.Model="{Binding . }" IsTabStop="False" />
</DataTemplate>
</helpers:AutobinderTemplateSelector.DocumentTemplate>
<helpers:AutobinderTemplateSelector.ToolTemplate>
<DataTemplate>
<ContentControl cal:View.Model="{Binding . }" IsTabStop="False" />
</DataTemplate>
</helpers:AutobinderTemplateSelector.ToolTemplate>
</helpers:AutobinderTemplateSelector>
</avalonDock:DockingManager.LayoutItemTemplateSelector>
<avalonDock:LayoutRoot>
<avalonDock:LayoutPanel Orientation="Horizontal">
<avalonDock:LayoutDocumentPane/>
<avalonDock:LayoutAnchorablePane Name="ToolsPane" DockWidth="240"/>
</avalonDock:LayoutPanel>
</avalonDock:LayoutRoot>
</avalonDock:DockingManager>
使用自定义类LayoutUpdateStrategy:
public class LayoutUpdateStrategy : ILayoutUpdateStrategy
{
public void AfterInsertAnchorable(LayoutRoot layout, LayoutAnchorable anchorableShown)
{}
public void AfterInsertDocument(LayoutRoot layout, LayoutDocument anchorableShown)
{}
public bool BeforeInsertAnchorable(LayoutRoot layout, LayoutAnchorable anchorableToShow, ILayoutContainer destinationContainer)
{
//AD wants to add the anchorable into destinationContainer
//just for test provide a new anchorablepane
//if the pane is floating let the manager go ahead
LayoutAnchorablePane destPane = destinationContainer as LayoutAnchorablePane;
if (destinationContainer != null &&
destinationContainer.FindParent<LayoutFloatingWindow>() != null)
return false;
var toolsPane = layout.Descendents().OfType<LayoutAnchorablePane>().FirstOrDefault(d => d.Name == "ToolsPane");
if (toolsPane != null)
{
toolsPane.Children.Add(anchorableToShow);
return true;
}
return false;
}
public bool BeforeInsertDocument(LayoutRoot layout, LayoutDocument anchorableToShow, ILayoutContainer destinationContainer)
{
return false;
}
}
自定义布局选择器:
class AutobinderLayoutSelector : StyleSelector
{
public Style DocumentStyle { get; set; }
public Style ToolStyle { get; set; }
public override Style SelectStyle(object item, DependencyObject container)
{
//check if the item is an instance of TestViewModel
if (item is IDockToolBar)
return DocumentStyle;
else if (item is IDockDocument)
return ToolStyle;
//delegate the call to base class
return base.SelectStyle(item, container);
}
}
和自定义TemplateSelector:
public class AutobinderTemplateSelector : DataTemplateSelector
{
public DataTemplate DocumentTemplate { get; set; }
public DataTemplate ToolTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
//check if the item is an instance of TestViewModel
if (item is IDockToolBar)
return DocumentTemplate;
else if (item is IDockDocument)
return ToolTemplate;
//delegate the call to base class
return base.SelectTemplate(item, container);
}
}
public class AutobinderTemplate : DataTemplate
{
}
public interface IDockToolBar {
bool IsVisible { get; set; }
}
public interface IDockDocument { }