C# 与绑定混淆&;ContentTemplate中的DataContext
考虑以下样式:C# 与绑定混淆&;ContentTemplate中的DataContext,c#,wpf,C#,Wpf,考虑以下样式: <Window.Resources> <Style x:Key="NumberButton" TargetType="Button"> <Setter Property="Width" Value="Auto"/> <Setter Property="Height" Value="Auto"/> <Setter Property="Margin" Value="2"/&g
<Window.Resources>
<Style x:Key="NumberButton" TargetType="Button">
<Setter Property="Width" Value="Auto"/>
<Setter Property="Height" Value="Auto"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Label Content="{Binding}" FontSize="20" FontFamily="Consolas"/>
</DataTemplate>
</Setter.Value>
</Setter>
<EventSetter Event="Click" Handler="OnClicked"/>
</Style>
</Window.Resources>
我的目标是能够创建多个按钮,每个按钮代表一个数字0-9。例如,下面是数字0的按钮:
<Button Grid.Row="3" Grid.Column="1" Style="{StaticResource NumberButton}" Content="0"/>
我对DataContext如何工作的理解是,如果您没有在XAML中显式地设置它,它应该为NULL,这指示绑定使用父级的DataContext。这是可传递的,因此它将继续向上移动每个父级,直到找到要使用的显式设置的DataContext
然而,我对绑定如何映射到内容
属性感到困惑。我知道ContentControl
的默认属性是Content
属性,但我从未在
元素上显式设置DataContext
。对我来说,这意味着按钮的DataContext为NULL,因此它将无法找到要显示的值
有人能解释一下,当我没有设置按钮的DataContext时,按钮的DataContext是如何被引用的吗?对于大多数控件,如果没有设置
DataContext
,它将使用父级DataContext
,通过继承的依赖属性完成<代码>内容控件和由此派生的控件,如按钮,工作方式稍有不同。如果您设置了这些控件的内容
,您还将数据上下文
设置为内容。因此,在您的示例中,DataContext
也是字符串“0”。Afair设置noContent
将断开继承的链,因此该按钮内的DataContext
将为空。您的猜测是正确的ContentControl的默认源属性为Content
。所以,通过这样做,{Binding}
,您明确地告诉绑定引擎将标签的内容属性绑定到按钮的内容属性
但假设您要绑定到button的DataContext中的某个属性-绑定DummyDataContext的Name属性,则必须这样做(假设DummyDataContext在根窗口上设置为DataContext):
和在数据模板中
<Label Content="{Binding Name}" FontSize="20" FontFamily="Consolas"/>
按钮的内容指向类DummyDataContext的实例。因此,当您在标签上绑定Content=“{Binding Name}”
时,您告诉它使用绑定到按钮内容的对象上的Name
属性进行绑定
希望它现在有意义 的
的DataContext
的特殊之处在于,它被设置为应用
的对象的Content
属性
在这种情况下,ContentTemplate
被应用于按钮
,因此ContentTemplate
中的DataContext
被设置为该按钮
的内容
属性,而按钮。Content
被设置为“0”
如果将此ContentTemplate
应用于具有不同Content
属性的不同按钮
,则将使用该Content
属性
这里有一个简单的例子,我希望能更好地说明这一点
<Button x:Name="OuterButton" Click="Button_Click">
<!-- // Set DataContext to a string equal to "OuterButton.DataContext" -->
<Button.DataContext>
OuterButton.DataContext
</Button.DataContext>
<!-- // Set Content to a string equal to "OuterButton.DataContext" -->
<Button.Content>
OuterButton.Content
</Button.Content>
<Button.ContentTemplate>
<DataTemplate>
<StackPanel>
<Button x:Name="InnerButton" Content="InnerButton.Content" Click="Button_Click" />
<TextBlock FontWeight="Bold" Text="{Binding }"/>
</StackPanel>
</DataTemplate>
</Button.ContentTemplate>
</Button>
我们这里有一个按钮。按钮的DataContext
和Content
属性设置为不同的值。该按钮还定义了一个内容模板
,其中包含另一个按钮
。此按钮的内容
属性设置为不同的值
单击任一按钮将输出所单击按钮的内容
和数据上下文
。请记住,内部按钮嵌套在外部按钮中,因此当您单击它时,两个按钮的click方法都会得到处理
单击内部按钮的最终结果:
InnerButton.DataContext: OuterButton.Content
InnerButton.Content: InnerButton.Content
OuterButton.DataContext: OuterButton.DataContext
OuterButton.Content: OuterButton.Content
InnerButton.DataContext:OuterButton.Content
InnerButton.Content:InnerButton.Content
OuterButton.DataContext:OuterButton.DataContext
内容:OuterButton.Content
如您所见,ContentTemplate
的特殊之处在于,它将DataContext
设置为它所应用到的任何对象的Content
属性。这种行为变化取决于我假设的特定层次结构?在我的具体案例中,任何来自ContentControl的驱动都会自动设置数据上下文,正如您所解释的那样?我找不到任何关于这种行为的官方文件。我不同意你的回答。如果设置ContentControl
的Content
属性,或从ContentControl
派生的控件,如按钮
,则它也不会设置该控件的DataContext
。但是,它确实使用Content
属性作为应用于该控件的任何ContentTemplate
的DataContext
,这可能就是您所想的。例如:)是的,你是对的,瑞秋。离代码还有几天,而且已经开始忘记东西了。那么{Binding}
没有绑定到DataContext
的值,就像我在网上读的那样?它绑定到类的默认属性?我听到了这么多相互矛盾的信息,这让我非常困惑:(你所说的也与Rachel在回答中所说的直接矛盾。你在这里混淆了事情。我在她的回答中也提到了Rachel所说的-的DataContext是特殊的,因为它被设置为要应用的对象的Content属性。
{Binding}与你读过的其他内容相比,内部内容模板的内容有所不同。Rachel,你总是让学习WPF变得更容易!!我将你的作为新答案标记。非常感谢,这让我非常清楚。
private void Button_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
Debug.WriteLine(string.Format("{0}.DataContext: {1}", btn.Name, btn.DataContext));
Debug.WriteLine(string.Format("{0}.Content: {1}", btn.Name, btn.Content));
}
InnerButton.DataContext: OuterButton.Content
InnerButton.Content: InnerButton.Content
OuterButton.DataContext: OuterButton.DataContext
OuterButton.Content: OuterButton.Content