忽略元数据覆盖?

时间:2011-03-25 11:06:00

标签: c# wpf metadata override

我做了一个非常简单的测试项目:

MainWindow.xaml:

<Window x:Class="Test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Test"
        Title="MainWindow" Height="350" Width="525" VerticalAlignment="Center" HorizontalAlignment="Center">

    <StackPanel x:Name="mainPanel" />

</Window>

MainWindow.xaml.cs:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Test
{
   public partial class MainWindow : Window
   {
      public MainWindow()
      {
         InitializeComponent();

            MyTextBox myTextBox = new MyTextBox("some text here");

            mainPanel.Children.Add(myTextBox);
      }
   }
}

MyTextBox.cs:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Test
{
    class MyTextBox : TextBox
    {
        static MyTextBox()
        {
            MyTextBox.BackgroundProperty.OverrideMetadata(typeof(MyTextBox), new FrameworkPropertyMetadata(Brushes.Red));
        }

        public MyTextBox(string Content)
        {
            Text = Content;
        }
    }
}

这个,为了测试metaData覆盖函数。

现在麻烦的是:这不像我预期的那样......

实际上,MyTextBox的背景是白色的,而不是红色。

我调查并尝试将其作为自定义类的构造函数:

public MyTextBox(string Content)
{
    Text = Content;
    Background = Brushes.Blue;
    ClearValue(BackgroundProperty);
}

现在这是我在调试时发现的:

主要课程中的

MyTextBox myTextBox = new MyTextBox("some text here");

我们进入自定义类的静态构造函数,然后进入实例的构造函数:

Text = Content;&gt;&gt;背景=红色

Background = Brushes.Blue;&gt;&gt;背景=蓝色

ClearValue(BackgroundProperty);&gt;&gt;背景=再次红色(如预期的那样)

我们回到主要课程:

mainPanel.Children.Add(myTextBox);

...就在这行代码之后,myTextBox.Background是白色。

问题:为什么?

为什么在将它添加到mainPanel时将其设置为白色?我找不到任何合乎逻辑的解释......

此外,如果我添加更多代码,我会执行以下操作:myTextBox.Background = Brushes.Blue;然后myTextBox.ClearValue(MyTextBox.BackgroundProperty);,它会再次变为蓝色然后是白色,而不是红色。

我不明白。

2 个答案:

答案 0 :(得分:2)

背景由TextBox的默认样式设置。基于Dependency Property Value Precedence Red位于#11,而默认Style位于#9。蓝色设置为#3,因此应该覆盖背景精细。

您可能必须明确设置背景(就像使用蓝色画笔一样),或者创建自己的不设置背景的自定义默认样式。您的默认样式可以基于TextBox版本。

答案 1 :(得分:2)

您可以在应用于Background的样式中设置MyTextBox

<Application.Resources>
    <Style TargetType="local:MyTextBox">
        <Setter Property="Background" Value="Red" />
    </Style>
</Application.Resources>

正如 CodeNaked 所提到的,默认元数据值正在被文本框的默认样式覆盖。如果您要更改代码,可以看到它:

MyTextBox.cs:

    Control.BackgroundProperty.OverrideMetadata(typeof(MyTextBox), new FrameworkPropertyMetadata(Brushes.Red, 
            FrameworkPropertyMetadataOptions.Inherits, PropertyChangedCallback));

    private static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        // set breakpoint here
    }

当断点断开时,您将能够看到OldValueRedNewValueWhite,并且从堆栈跟踪中您可以看到它发生,因为正在应用的默认样式。