DependencyProperty 编译并工作,但 Intellisense 不这么认为

DependencyProperty compiles and works but Intellisense doesn't think so

我有两个自定义 controls/visuals,我都需要一个 Orientation 属性。在这两种情况下,默认值应该是 "Horizontal" 但 control/visual 的用户应该能够指定 Orientation="Vertical" 以垂直排列 control/visual 的组件。我所拥有的在我的 ImageButton 控件上效果很好,但在我的 HeaderedLabel 视觉效果上效果不佳。虽然它们都编译得很好,但 Intellisense 不喜欢其中一个。这是它们的使用示例...

<Visuals:ImageButton Image="Icons/ok.png" Content="Normal Content"/>
<Visuals:ImageButton Image="Icons/ok.png" Content="Vertical Content" Orientation="Vertical"/>
<Visuals:HeaderedLabel Header="Normal Header" Content="Normal Content"/>
<Visuals:HeaderedLabel Header="Vertical Header" Content="Vertical Content" Orientation="Vertical"/>

...在垂直 StackPanel 内呈现时会产生以下内容:

所以它做了我想要的,但问题是:虽然 Intellisense 识别 Orientation ImageButton 的可能选项,但 它不识别可能的选项HeaderedLabelOrientation 选项。虽然代码可以正常编译和运行,但 Visual Studio "Error List" 窗格中存在持续错误: "'Vertical' 不是 属性 'Orientation' 的有效值。”, 文本下方有一条蓝色波浪线 Orientation="Vertical" 用于我上面 xaml 示例中的第二个 HeaderedLabel。

相关文件如下:

// File 'ImageButton.cs'
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Visuals
{
   public class ImageButton : Button
   {
      static ImageButton()
      {
         DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageButton),
            new FrameworkPropertyMetadata(typeof(ImageButton)));
      }

      public ImageSource Image
      {
         get { return (ImageSource)GetValue(ImageProperty); }
         set { SetValue(ImageProperty, value); }
      }

      public Orientation Orientation
      {
         get { return (Orientation)GetValue(OrientationProperty); }
         set { SetValue(OrientationProperty, value); }
      }

      // Note that for ImageButton, I can just say 'Orientation.Horizontal' and
      // the compiler resolves that to System.Windows.Controls.Orientation...
      public static readonly DependencyProperty OrientationProperty =
         DependencyProperty.Register("Orientation", typeof(Orientation),
            typeof(ImageButton), new UIPropertyMetadata(Orientation.Horizontal));

      public static readonly DependencyProperty ImageProperty =
         DependencyProperty.Register("Image", typeof(ImageSource),
            typeof(ImageButton), new UIPropertyMetadata(null));
   }
}

.

// File 'HeaderedLabel.cs'
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Visuals
{
   public class HeaderedLabel : Control
   {
      static HeaderedLabel()
      {
         DefaultStyleKeyProperty.OverrideMetadata(typeof(HeaderedLabel),
            new FrameworkPropertyMetadata(typeof(HeaderedLabel)));
      }

      public object Header
      {
         get { return (object)GetValue(HeaderProperty); }
         set { SetValue(HeaderProperty, value); }
      }

      public object Content
      {
         get { return (object)GetValue(ContentProperty); }
         set { SetValue(ContentProperty, value); }
      }

      public object Orientation
      {
         get { return (object)GetValue(OrientationProperty); }
         set { SetValue(OrientationProperty, value); }
      }

      public static readonly DependencyProperty HeaderProperty =
         DependencyProperty.Register("Header", typeof(object), typeof(HeaderedLabel),
            new UIPropertyMetadata(null));

      public static readonly DependencyProperty ContentProperty =
         DependencyProperty.Register("Content", typeof(object), typeof(HeaderedLabel),
            new UIPropertyMetadata(null));

      // Note that for HeaderedLabel, unlike ImageButton, I have to specify the fully-
      // qualified name of 'Orientation.Horizontal', otherwise the compiler resolves it
      // to Visuals.HeaderedLabel.Orientation and gives a compiler error...
      public static readonly DependencyProperty OrientationProperty =
         DependencyProperty.Register("Orientation", typeof(System.Windows.Controls.Orientation),
            typeof(HeaderedLabel), new UIPropertyMetadata(System.Windows.Controls.Orientation.Horizontal));
   }
}

.

   <!-- File 'Generic.xaml' -->
   <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                        xmlns:local="clr-namespace:Visuals"
                        xmlns:bind="clr-namespace:Visuals.BindingConverters">

       <Style TargetType="{x:Type local:ImageButton}">
          <Setter Property="Template">
             <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:ImageButton}">
                   <Button>
                      <StackPanel Orientation="{TemplateBinding Orientation}">
                         <Image Source="{TemplateBinding Image}"/>
                         <ContentPresenter/>
                      </StackPanel>
                   </Button>
                </ControlTemplate>
             </Setter.Value>
          </Setter>
       </Style>

       <Style TargetType="{x:Type local:HeaderedLabel}">
          <Setter Property="Template">
             <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:HeaderedLabel}">
                   <StackPanel Orientation="{TemplateBinding Orientation}">
                      <StackPanel Orientation="Horizontal">
                         <ContentControl Content="{TemplateBinding Header}" />
                         <TextBlock Text=":" />
                      </StackPanel>
                      <ContentControl Content="{TemplateBinding Content}"/>
                   </StackPanel>
                </ControlTemplate>
             </Setter.Value>
          </Setter>
       </Style>

    </ResourceDictionary>

知道为什么编译器会将 ImageButton 的 Orientation.Horizontal 解析为 System.Windows.Controls.Orientation.Horizontal,但不会将 HeaderedLabel 解析为 System.Windows.Controls.Orientation.Horizontal 吗?更重要的是,为什么 Intellisense 无法找出 HeaderedLabel.Orientation?

的选项?

顺便说一句,我使用的是 VisualStudio 2012 和 .NET Framework 4.0。

您的所有属性,包括 Orientation 属性,都声明为类型 object

你应该改用这个:

public Orientation Orientation
{
    get { return (Orientation)GetValue(OrientationProperty); }
    set { SetValue(OrientationProperty, value); }
}

如果您正确声明 属性,XAML 编辑器应该能够正确接受类型 Orientation 的值。否则,它将尝试将 "Vertical"string 值分配给 属性,当传递给 SetValue() 方法时将失败,因为 DependencyProperty 对象本身是用 Orientation 作为有效类型初始化的,它无法从 string 值转换为 Orientation 值。

如果您正确声明 属性,WPF 将自动理解它需要将 XAML 中显示的 string 值转换为 Orientation 值属性(即将 string 值解析为适当的 enum 类型),在这种情况下初始化应该有效。