与ContentTemplate中的Bindings和DataContext混淆

voi*_*ter 3 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"/>
        <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>
Run Code Online (Sandbox Code Playgroud)

我的目标是能够创建多个按钮,每个按钮代表一个0-9的数字.例如,这是数字0的按钮:

<Button Grid.Row="3" Grid.Column="1" Style="{StaticResource NumberButton}" Content="0"/>
Run Code Online (Sandbox Code Playgroud)

我对DataContext如何工作的理解是,如果你没有在XAML中显式设置它,它应该是NULL,它指示绑定使用父的DataContext.这是可传递的,因此它将继续向上移动每个父级,直到找到要使用的显式设置的DataContext.

然而,我对我的绑定如何映射到Content属性感到困惑.我知道ContentControl的默认属性是Content财产,但我从来没有明确设置DataContext<Button>的元素.对我来说,这意味着Button的DataContext为NULL,因此无法找到要显示的值.

有人可以解释当我没有设置Button时如何引用Button的DataContext?

Rac*_*hel 7

DataContext<ContentTemplate>特殊之处在于它被设置为要应用Content的对象的属性<ContentTemplate>.

在这种情况下,ContentTemplate正在应用于a Button,因此将其DataContext内部ContentTemplate设置为该Content属性Button,并将Button.Content其设置为"0"

如果将此ContentTemplate应用于Button具有不同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>
Run Code Online (Sandbox Code Playgroud)
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));
}
Run Code Online (Sandbox Code Playgroud)

我们这里有一个按钮.Button DataContextContent属性设置为不同的值.该按钮还有一个已ContentTemplate定义的,其中包含另一个Button.此按钮的Content属性设置为不同的值.

单击任一按钮将输出单击的按钮ContentDataContext.请记住,内部按钮嵌套在OuterButton中,因此当您单击它时,将为两个按钮处理Click方法.

单击内部按钮的最终结果:

InnerButton.DataContext: OuterButton.Content
InnerButton.Content: InnerButton.Content

OuterButton.DataContext: OuterButton.DataContext
OuterButton.Content: OuterButton.Content

正如您所看到的,a ContentTemplate的特殊之处在于它将其应用于任何对象DataContextContent属性设置为.