我有两个自定义控件/视觉效果,我需要两个Orientation
属性。在这两种情况下,默认值应为"Horizontal"
,但控件/视觉用户应该能够指定Orientation="Vertical"
来垂直排列控件/视觉组件。我的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识别出ImageButton的Orientation
的可能选项, 但它无法识别的可能选项 Orientation
for HeaderedLabel 。虽然代码编译和放大运行正常, Visual Studio“错误列表”窗格中存在持久性错误: “'垂直'不是属性'Orientation'的有效值。”, 在上面的xaml示例中,第二个HeaderedLabel文本 Orientation="Vertical"
下面有一条蓝色波浪线。
以下是相关文件:
// 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>
为什么编译器会将Orientation.Horizontal
解析为ImageButton的System.Windows.Controls.Orientation.Horizontal,而不是HeaderedLabel?更重要的是,为什么Intellisense无法找出HeaderedLabel.Orientation的选项?
BTW,我正在使用VisualStudio 2012和.NET Framework 4.0。
答案 0 :(得分:3)
您的所有属性(包括Orientation
属性)都声明为object
类型。
你应该改为:
public Orientation Orientation
{
get { return (Orientation)GetValue(OrientationProperty); }
set { SetValue(OrientationProperty, value); }
}
如果正确声明属性,XAML编辑器应该能够正确接受Orientation
类型的值。否则,它将尝试将string
值"Vertical"
分配给属性,当传递给SetValue()
方法时,该属性将失败,因为DependencyProperty
对象本身已初始化为Orientation
作为有效类型,无法将string
值转换为Orientation
值。
如果你正确地声明了属性,那么WPF会自动理解它需要将XAML中显示的string
值转换为属性的Orientation
值(即解析string
} value作为适当的enum
类型),在这种情况下初始化应该有效。