c# - 与 ContentTemplate 中的 Bindings 和 DataContext 混淆

标签 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>

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

<Button Grid.Row="3" Grid.Column="1" Style="{StaticResource NumberButton}" Content="0"/>

我对 DataContext 工作原理的理解是,如果您没有在 XAML 中明确设置它,则它应该为 NULL,这会指示绑定(bind)改用父级的 DataContext。这是可传递的,因此它将继续向上移动每个父级,直到找到要使用的显式设置的 DataContext。

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

谁能解释一下,当我没有设置按钮的 DataContext 时,它是如何被引用的?

最佳答案

DataContext<ContentTemplate>特殊之处在于它被设置为 Content对象的属性<ContentTemplate>正在申请。

在这种情况下,ContentTemplate正在应用于 Button , 所以 DataContextContentTemplate里面设置为 Content那的属性(property)Button , 和 Button.Content设置为 "0"

如果您应用此 ContentTemplate到另一个Button用不同的Content属性(property),即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>
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));
}

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

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

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

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

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

如您所见,ContentTemplate特殊之处在于它设置了 DataContextContent它适用于任何对象的属性。

关于c# - 与 ContentTemplate 中的 Bindings 和 DataContext 混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20830744/

相关文章:

wpf - Button.WPF MVVM中的属性的选定类型吗?

c# - wpf datagrid 根据选定的值生成行

c# - WPF 自定义框架元素/IScrollInfo

c# - Autofac - 我可以使用 Microsoft.Extensions.DependencyInjection 的注册样式代替 Autofac 吗?

c# - 使用动态表达式对组进行 IQueryable LINQ 转换错误

c# - 带有 ASP.NET MVC 的 C# 中的通知系统/服务

c# - 为什么我的 TreeView 仅显示一层深度?

c# - 如何拉伸(stretch)图像以填充此 WPF/XAML 应用程序?

c# - HTTP Get请求错误 "Authentication failed because the remote party has closed the transport stream."

c# - 将 XmlNodeList 转换为 XmlNode[]