我已经在这几个星期了...我正在创建一个在主窗口中使用 Avalon Dock 2.0 的 WPF 应用程序。我正在尝试以 MVVM 方式使用对接管理器,所以我有 DockingManager.DocumentsSource
绑定(bind)到 ObservableCollection<object>
我的属性(property)MainViewModel
.我还创建了一个自定义 DataTemplateSelector
并将其绑定(bind)到 DockingManager.LayoutItemTemplateSelector
.我遇到的问题:
- 我添加一个
ViewModel
到文件来源。 - 我的习惯
DataTemplateSelector.SelectTemplate()
被称为。 -
SelectTemplate()
中的项目参数是System.Windows.Controls.ContentPresenter
而不是ViewModel
我添加的对象。 - 即使我返回正确的
DataTemplate
, 它最终绑定(bind)到ContentPresenter
而不是ViewModel
包含在ContentPresenter
中.
我设法在一个基本的 WPF 项目中复制了这个问题,这里是相关代码:
主窗口:
<!-- MainWindow markup DataContext is bound to
I omitted the usual xmlns declarations -->
<Window
xmlns:xcad="http://schemas.xceed.com/wpf/xaml/avalondock"
xmlns:local="clr-namespace:AvalonTest"
Title="MainWindow">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<xcad:DockingManager DocumentsSource="{Binding Docs}">
<xcad:DockingManager.LayoutItemTemplateSelector>
<local:TestTemplateSelector>
<local:TestTemplateSelector.TheTemplate>
<DataTemplate>
<local:TestView/>
</DataTemplate>
</local:TestTemplateSelector.TheTemplate>
</local:TestTemplateSelector>
</xcad:DockingManager.LayoutItemTemplateSelector>
<xcad:LayoutRoot>
<xcad:LayoutPanel Orientation="Vertical">
<xcad:LayoutAnchorablePane/>
<xcad:LayoutDocumentPane/>
</xcad:LayoutPanel>
</xcad:LayoutRoot>
</xcad:DockingManager>
</Grid>
</Window>
主视图模型:
class MainViewModel
{
//Bound to DockingManager.DocumentsSource
public ObservableCollection<object> Docs { get; private set; }
public MainViewModel()
{
Docs = new ObservableCollection<object>();
Docs.Add(new TestViewModel());
}
}
数据模板选择器:
class TestTemplateSelector : DataTemplateSelector
{
public TestTemplateSelector() {}
public DataTemplate TheTemplate { get; set; }
//When this method is called, item is always a ContentPresenter
//ContentPresenter.Content will contain the ViewModel I add
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
//Just return the only template no matter what
return TheTemplate;
}
}
测试 View :
<!-- TestTemplateSelector will always return this TestView -->
<UserControl x:Class="AvalonTest.TestView"
xmlns:local="clr-namespace:AvalonTest">
<Grid>
<StackPanel Orientation="Vertical">
<TextBox Text="{Binding TestText}"/>
<Button Content="A Button"/>
</StackPanel>
</Grid>
</UserControl>
测试 View 模型:
//TestView.DataContext should be set to this, but instead
//it gets set to a containing ContentPresenter
class TestViewModel : ObservableObject
{
private string testText = "TESTTESTTEST";
public string TestText
{
get { return testText; }
set
{
testText = value;
RaisePropertyChanged("TestText");
}
}
}
结果:
TestView
未正确绑定(bind)到 TestViewModel
因此“TESTTESTTEST”不会出现在 TextBox
中.我已经 checkout Avalon Dock's sample MVVM project和他们的 DataTemplateSelector
总是得到 ViewModel
而不是 ContentPresenter
.我做错了什么?
最佳答案
如下更改 TestTemplateSelector 上 SelectTemplate 的定义:
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
//check if the item is an instance of TestViewModel
if (item is TestViewModel)
return TheTemplate;
//delegate the call to base class
return base.SelectTemplate(item, container);
}
您应该始终检查传递的项目是否是目标 View 模型的实例,如果不是,则将调用委托(delegate)给基类,以便 WPF 可以处理您不关心的对象。
关于c# - Avalon Dock 2.0 LayoutItemTemplateSelector 给出了 ContentPresenter 而不是 ViewModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32580286/