Avalon Dock 2.0 LayoutItemTemplateSelector 给出了 ContentPresenter 而不是 ViewModel
Avalon Dock 2.0 LayoutItemTemplateSelector given ContentPresenter instead of ViewModel
我已经在这几个星期了...我正在创建一个 WPF 应用程序,它在 Main Window 中使用 Avalon Dock 2.0。我正在尝试以 MVVM 方式使用对接管理器,因此我在 MainViewModel
中将 DockingManager.DocumentsSource
绑定到 ObservableCollection<object>
属性。我还创建了一个自定义 DataTemplateSelector
并将其绑定到 DockingManager.LayoutItemTemplateSelector
。我遇到的问题:
- 我在文档源中添加了一个
ViewModel
。
- 调用了我的自定义
DataTemplateSelector.SelectTemplate()
。
SelectTemplate()
中的项目参数是 System.Windows.Controls.ContentPresenter
而不是我添加的 ViewModel
对象。
- 即使我 return 是正确的
DataTemplate
,它最终会绑定到 ContentPresenter
,而不是 ContentPresenter
中包含的 ViewModel
。
我设法在一个基本的 WPF 项目中复制了这个问题,这里是相关代码:
主要Window:
<!-- 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;
}
}
测试视图:
<!-- 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>
测试视图模型:
//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
没有正确绑定到 TestViewModel
,因此 "TESTTESTTEST" 没有出现在 TextBox
中。我查看了 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);
}
您应该始终检查传递的项目是否是目标视图模型的实例,如果不是,则将调用委托给基础 class,以便 WPF 可以处理您不关心的对象.
我已经在这几个星期了...我正在创建一个 WPF 应用程序,它在 Main Window 中使用 Avalon Dock 2.0。我正在尝试以 MVVM 方式使用对接管理器,因此我在 MainViewModel
中将 DockingManager.DocumentsSource
绑定到 ObservableCollection<object>
属性。我还创建了一个自定义 DataTemplateSelector
并将其绑定到 DockingManager.LayoutItemTemplateSelector
。我遇到的问题:
- 我在文档源中添加了一个
ViewModel
。 - 调用了我的自定义
DataTemplateSelector.SelectTemplate()
。 SelectTemplate()
中的项目参数是System.Windows.Controls.ContentPresenter
而不是我添加的ViewModel
对象。- 即使我 return 是正确的
DataTemplate
,它最终会绑定到ContentPresenter
,而不是ContentPresenter
中包含的ViewModel
。
我设法在一个基本的 WPF 项目中复制了这个问题,这里是相关代码:
主要Window:
<!-- 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;
}
}
测试视图:
<!-- 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>
测试视图模型:
//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
没有正确绑定到 TestViewModel
,因此 "TESTTESTTEST" 没有出现在 TextBox
中。我查看了 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);
}
您应该始终检查传递的项目是否是目标视图模型的实例,如果不是,则将调用委托给基础 class,以便 WPF 可以处理您不关心的对象.