我正在构建一个基于article by Sukram in CodeProject的图形设计器。我现在正在尝试扩展它,以便画布上的每个项目绑定到不同的ViewModel对象 - 即我为每个项目设置DataContext。
设计器上的每个项目实际上都是一个ContentControl,其中放置了一个不同的模板(基于哪个工具箱项目被拖动到画布上)。所以我有一个包含TextBox的模板,我有一个包含Name属性的ViewModel对象,我将TextBox的Text属性绑定到ViewModel的Name属性,并且......没有。我用Snoop检查了可视化树,它确认了TextBox的DataContext是ViewModel对象。然而TextBox仍然是空的。如果我修改TextBox中的(空)文本,ViewModel中的Name属性不会更改。所以看起来绑定没有应用(或者已经被删除)。
我发现了一些帖子,其中讨论了ContentControl与DataContext和Content属性混淆,但我不确定它们的适用性如何。代码设置ContentControl.Content,如下所示:
newItem = new ContentControl();
ControlTemplate template = toolbox.GetTemplate();
UIElement element = template.LoadContent() as UIElement;
ViewModelItem viewModel = new ViewModelItem() { Name = "Bob" };
newItem.Content = element;
newItem.DataContext = viewModel;
,模板的XAML是:
<ControlTemplate>
<Border BorderBrush="Black" BorderThickness="1" Width="100">
<TextBox Text={Binding Name}/>
</Border>
</ControlTemplate>
Snoop显示TextBox有一个DataContext,如果我Delve那个DataContext,我可以看到它有一个Name属性,其值为“Bob”。那么为什么TextBox保持空? Snoop允许我更改Name属性,但TextBox保持为空。
我做错了什么?
更多细节。我已经将OutputWindow的VS2010 Debug DataBinding选项设置为Verbose,这似乎表明在我设置DataContext之前正在尝试绑定。是否有可能无法识别对DataContext的更改?
我刚发现这篇文章DataTemplate.LoadContent does not preserve bindings - 显然DataTemplate.LoadContent不保留绑定。所以看起来我必须编写自己的LoadContent()版本。
我已经意识到模板已经通过XamlWriter,它显然剥离了所有绑定。这没有用。
我无法修复DataTemplate.LoadContent(),但我意识到我实际上并不需要DataTemplate,因为XamlWriter / XamlReader已经实例化了我之后的UI元素。我找到了一个修复程序,让XamlWriter编写所有绑定here,之后一切正常。
感谢您的帮助。
答案 0 :(得分:0)
也许你需要告诉ControlTemplate
中的绑定来查看TemplatedParent
,this thread中提到了什么?
<TextBox Text="{Binding Path=Name, RelativeSource={RelativeSource TemplatedParent}}"/>
要么是这样,要么尝试使用DataTemplate
。
此刻我无法对此进行测试,所以我可能只是在这里猜测。
答案 1 :(得分:0)
我会使用DataTemplate
,正如bde建议的那样。
您正试图在自己的数据(ViewModel)上放置一些用户界面,这就是数据 - 模板的含义(ControlTemplate
通常是如果你想要change how e.g. a Button
looks),你会使用什么。
将您的代码更改为ContentControl.ContentTemplate
使用DataTemplate
:
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1" Width="100">
<TextBox Text={Binding Name}/>
</Border>
</DataTemplate>
代码隐藏:
newItem = new ContentControl();
//NOTE: .GetTemplate() needs to return a DataTemplate, and not a ControlTemplate:
newItem.ContentTemplate = toolbox.GetTemplate();
ViewModelItem viewModel = new ViewModelItem() { Name = "Bob" };
newItem.Content = viewModel;
newItem.DataContext = viewModel;