ContentControl内部的绑定不起作用

3
我正在构建一个基于Sukram在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,如果我深入该DataContext,可以看到它具有一个Name属性,其值为“Bob”。那么为什么TextBox仍然为空?尽管Snoop允许我更改该Name属性,但TextBox仍然为空。我做错了什么?
一些细节。我已将VS2010调试数据绑定选项设置为Verbose,这似乎显示了在设置DataContext之前就尝试了所有绑定。改变DataContext可能无法被识别,这是可能的吗?

我刚刚发现了这篇文章 DataTemplate.LoadContent does not preserve bindings - 显然 DataTemplate.LoadContent 不会保留绑定。所以看起来我必须编写自己的 LoadContent() 版本。


我意识到模板经过 XamlWriter 处理后会剥离所有绑定,这对于解决问题没有帮助。


我无法修复DataTemplate.LoadContent(),但我意识到我实际上并不需要DataTemplate,因为XamlWriter / XamlReader已经实例化了我需要的UI元素。我找到了一个解决方案,让XamlWriter编写所有绑定here,之后一切都正常工作了。
感谢您的帮助。
2个回答

0
也许你需要告诉ControlTemplate中的绑定去关注TemplatedParent,就像this thread所提到的那样?
<TextBox Text="{Binding Path=Name, RelativeSource={RelativeSource TemplatedParent}}"/>

要么尝试使用 DataTemplate

我现在无法测试,所以可能只是猜测。


谢谢建议,但那并没有起作用。我还尝试将DataContext绑定到ContentControl内部的元素上,Snoop显示它已经传递到TextBox了,但那也不起作用。所有这些的困难在于我不知道如何调试这个绑定问题。我可以使用Snoop看到TextBox的DataContext是正确的,但我不知道为什么绑定不起作用——没有引发任何异常,输出窗口中也没有任何信息。现在似乎只剩下随机尝试各种不同类型的绑定参数了。 - user1951972
是的,在WPF中调试绑定问题并不容易。除了VS中有时会显示绑定错误消息的“输出”窗口之外,我不知道还有什么工具可以帮助解决这个问题。如果您无法让控件模板正常工作,那么可能需要改用“DataTemplate”。 - WildCrustacean

0

我会像bde建议的那样使用。

您正在尝试将一些UI放在自己的数据(ViewModel)上,这就是Data-Templates的用途(如果您想更改例如


谢谢您的建议 - 它很有道理,所以我已经尝试了,但是没有任何改变。Snoops显示TextBox具有正确的DataContext,但名称仍未显示。还有其他想法吗? - user1951972
你如何在 toolbox.GetTemplate() 中加载模板呢?你能贴出那个函数吗? - Sphinxxx
GetTemplate()只是一个普通的附加属性,即: - user1951972
`public static readonly DependencyProperty DesignerElementProperty = DependencyProperty.RegisterAttached("DesignerElement", typeof(FrameworkElement), typeof(DesignerItem)); public static FrameworkElement GetDesignerElement(UIElement element) { Object value = element.GetValue(DesignerElementProperty); return (FrameworkElement)value; }` - user1951972
那是一些DesignerElement属性的代码,而不是GetTemplate()方法。我不确定我是否理解了你的解决方案,但是阅读了你更新的问题后,我发现你已经修复了它,所以我猜一切都好了 :) - Sphinxxx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接