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 的可能选项,但 它不识别可能的选项HeaderedLabel 的 Orientation
选项。虽然代码可以正常编译和运行,但 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
类型),在这种情况下初始化应该有效。
我有两个自定义 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 的可能选项,但 它不识别可能的选项HeaderedLabel 的 Orientation
选项。虽然代码可以正常编译和运行,但 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
类型),在这种情况下初始化应该有效。