在 XAML 中更改某些用户控件属性不会在 运行 应用程序之前发生

Changing some user control attributes in XAML doesn't take place before running the application

我有一个自定义 UserControl,它基本上只是一个带有标题和一些内容的奇特容器:

这就是我在 XAML:

中使用它的方式
<local:MDCard Header="Some Title">
<Grid>
...
...
</Grid>
</local:MDCard>

问题是在设计时(在 运行 代码之前)这是我在图形 XAML 编辑器中看到的:

请注意标题未显示。

这是我的 UserControl:

的源代码
<UserControl x:Class="HealthAndWellBeing.MDCard"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:HealthAndWellBeing"
         mc:Ignorable="d" 
         d:DesignHeight="300"
         d:DesignWidth="300"
         x:Name="self">
<UserControl.Template>
    <ControlTemplate TargetType="{x:Type UserControl}">
        <Grid>
            <Grid>
                <Grid.Effect>
                    <DropShadowEffect Direction="270" ShadowDepth="1" Opacity="0.2" BlurRadius="2"/>
                </Grid.Effect>
                <Grid>
                    <Grid.Effect>
                        <DropShadowEffect Direction="270" ShadowDepth="0" Opacity="0.12" BlurRadius="8"/>
                    </Grid.Effect>
                    <Grid>
                        <Grid.Effect>
                            <DropShadowEffect Direction="270" ShadowDepth="1" Opacity="0.14"/>
                        </Grid.Effect>
                        <Border Background="#FFFAFAFA" CornerRadius="2"/>
                    </Grid>
                </Grid>
            </Grid>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto"/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <Border Grid.Row="0" BorderThickness="0,0,0,1" BorderBrush="#19000000">
                    <Label FontWeight="Bold" Foreground="#FF616161" Margin="10,10,10,10">
                        <ContentPresenter Content="{Binding Header}"/>
                    </Label>
                </Border>
                <ContentPresenter Grid.Row="1"/>
            </Grid>
        </Grid>
    </ControlTemplate>
</UserControl.Template>

这是我的 code-behind:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace HealthAndWellBeing
{
    /// <summary>
    /// Interaction logic for MDCard.xaml
    /// </summary>
    public partial class MDCard : UserControl, INotifyPropertyChanged
    {
        public MDCard()
        {
            InitializeComponent();
            DataContext = this;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyChange(string PropertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
        }

        public string Header
        {
            get { return (string)GetValue(HeaderProperty); }
            set { SetValue(HeaderProperty, value); }
        }
        public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register("Header", typeof(string), typeof(MDCard), new PropertyMetadata("Title"));
    }
}

那么为什么当我更改 Button 的文本时可以立即在图形 XAML 编辑器中看到它,但更改我的自定义 [=] 的 Header 15=]只能在运行时间看到?

本质上,将标签的 Binding-Signature 从

更改为
<Label FontWeight="Bold" Foreground="#FF616161" Margin="10,10,10,10">
   <ContentPresenter Content="{Binding Header}"/>
</Label>

<Label FontWeight="Bold" Foreground="#FF616161" Margin="10,10,10,10">
   <ContentPresenter Content="{Binding Header, RelativeSource={RelativeSource TemplatedParent}}"/>
</Label>

应该/可以解决问题。

毕竟你不是要解析 ControlTemplate 的 属性 Header 你要给 UserControl,而是 UserControl 的后代=14=] class 有一个 DependencyProperty 叫做 Header。 这就是为什么您应该绑定到 TemplatedParent,即 actual UserControl 后代。

在 CustomControl 的情况下,您使用 compile-time 绑定 TemplateBinding,因为您正在模板化这个特定的 class.

使用 UserControls 但是您使用 Bindings,它们在运行时通过 System.Reflection 解析。这就是为什么你应该告诉它寻找一个特定的 parent,如果它不是那个特定 class 的 属性。在这种情况下 TemplatedParent.

但是可以找到 Binding 与 TemplatedBinding 之间更好的解释 here

我只能假设 "real" WPF 运行时库将简单地帮助您解决实际的 DependencyProperty - 混合(VS 设计器)不会。