SILVERLIGHT自定义控件

daview 2010-05-10 01:36:07
我想写个自定义控件,继承自CONTENTCONTROL或CONTROL或PANEL等都可以考虑,目前遇到这样的问题:



我想设置一些属性,比如CONTENT,当用户有设置的时候,使用用户设置的,当用户不配置的时候使用内置的。



比如:



我对CONTENTCONTROL派生的控件增加了一个HEADER的属性,希望当用户设置HEADER的时候,显示用户设置的HEADER内容,不设置的时候,显示默认的。



我在操作中如下处理:



1——

定义一个DEPENDENCYPROPERTY:HEADERPROPERTY

2——

在模板中设置一个HEADER对象的CONTENTCONTROL,其内容绑定到HEADER属性

3——

在控件的STYLE中,通过SETTER设置HEADER的值



问题:

1——

当我设置的HEADER为简单的内容(非可视化对象,比如文本、数字等)的时候,一切都OK。但当我设置为一个UI对象的时候,报告错误。

2——

我通过ONAPPLYTEMPLATE方法来获取这个SETTER设置的值,然后再设置到HEADER对象的CONTENT上,报告这个UI对象已经是别的对象的子对象了,而跟踪显示,该对象的PARENT为空。
...全文
466 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
websco 2010-05-12
  • 打赏
  • 举报
回复
我觉楼主的 HEADER 的一般思想这样实现: HEADER 是一个 ContentPresenter ,本身有一个默认 Style ,通过外部进行重新赋一个新的 Style (含有ItemTemplate)以更改其外观, 而通过外部重新赋值为新的 Content,则可以使用新的 Content 替换掉 ContentPresenter 。 ContentPresenter 就是起到一个控件的占位符的作用。
daview 2010-05-12
  • 打赏
  • 举报
回复
感谢两位。

HEADER只不过是我的举例而已。

我的目标就是:

1——
自己写一个自定义控件。毕竟TOOLKIT里的控件有限,使用上也难尽如人意。

2——
在控件中,会有个类似HEADER的DEPENDENCYPROPERTY的属性,类型为UIELEMENT或OBJECT都可以考虑。

3——
HEADER是控件UI的一个部分。在使用的时候可以通过“CLASS.HEADER”的形式设置其具体的内容。

4——
我希望在使用这个控件没设置HEADER属性的时候,能有一个默认的值,比如“MY HEADER”。


如果只是实现上面1-3步功能,已经没问题,我的问题是第四步的实现。

初始,我通过对一个UI控件(比如CONTENTCONTROL)设置其STYLE,在STYLE中配置CONTENTPRESENTER来解决。问题是不能默认设置CONTENTPRESENTER的CONTENT值,设置了后,应用时使用HEADER的设置是无效的。

接着,我又通过控件模板在STYLE中通过SETTER设置HEADER的初始值,结果是:如果HEADER的内容是普通的值,比如字符串、数字等是没问题,如果是UI对象,则不行。没起到效果。

于是,我又通过STYLE管理器,把通过SETTER设置的HEADER值取出来,然后强行赋值到HEADER容器控件的CONTENT中,报告了错误:子控件已经属于另外一个容器控件(具体文字忘记了,意思是这个)。

现在我的解决方案是:

在设置DEPENDENCYPROPERTY的时候设置默认值,这个好处理,关键是我这个默认值怎么生成。我目前采用的是通过定义XAML字符串,然后通过XAMLREADER来加载处理,感觉这个有点怪,脱离了UI与控件控制代码分离的思想。另外一个可以考虑的方案是定义额外的一个控件,专门用来做默认值,此方案感觉也是无奈之举。


jv9 2010-05-11
  • 打赏
  • 举报
回复
不知道楼主说的报错是什么错误?
我写过一些自定义控件,你可以参考下面的例程:


Private FullRect As RectangleGeometry
Private HeaderRect As RectangleGeometry
Private HeaderContainer As ContentControl

'Public Event evt As SizeChangedEventHandler

''' <summary>
''' Create a new instance of the GroupBox control.
''' </summary>
Sub New()
DefaultStyleKey = GetType(GroupBox)
AddHandler SizeChanged, AddressOf GroupBox_SizeChanged
End Sub

''' <summary>
''' Build the visual tree for the GroupBox control when the template is applied.
''' </summary>
Public Overrides Sub OnApplyTemplate()
MyBase.OnApplyTemplate()

FullRect = CType(GetTemplateChild("FullRect"), RectangleGeometry)
HeaderRect = CType(GetTemplateChild("HeaderRect"), RectangleGeometry)
HeaderContainer = CType(GetTemplateChild("HeaderContainer"), ContentControl)

AddHandler HeaderContainer.SizeChanged, AddressOf HeaderContainer_SizeChanged

End Sub

''' <summary>
''' Header Dependency Property
''' </summary>
Public Shared ReadOnly HeaderProperty As DependencyProperty = _
DependencyProperty.Register("Header", GetType(Object), GetType(GroupBox), Nothing)

''' <summary>
''' The Header for the GroupBox
''' </summary>
Public Property Header() As Object
Get
Return GetValue(HeaderProperty)
End Get
Set(ByVal value As Object)
SetValue(HeaderProperty, value)
End Set
End Property

''' <summary>
''' HeaderTemplate dependency property
''' </summary>
Public Shared ReadOnly HeaderTemplateProperty As DependencyProperty = _
DependencyProperty.Register("HeaderTemplate", GetType(DataTemplate), GetType(GroupBox), Nothing)

''' <summary>
''' The Header DataTemplate
''' </summary>
Public Property HeaderTemplate() As DataTemplate
Get
Return CType(GetValue(HeaderTemplateProperty), DataTemplate)
End Get
Set(ByVal value As DataTemplate)
SetValue(HeaderTemplateProperty, value)
End Set
End Property

Private Sub GroupBox_SizeChanged(ByVal sender As Object, ByVal e As SizeChangedEventArgs)
FullRect.Rect = New Rect(New Point(), e.NewSize)
End Sub

Private Sub HeaderContainer_SizeChanged(ByVal sender As Object, ByVal e As SizeChangedEventArgs)
HeaderRect.Rect = New Rect(New Point(HeaderContainer.Margin.Left, 0), e.NewSize)
End Sub
websco 2010-05-11
  • 打赏
  • 举报
回复
在 Style 中设置的 Header ? 楼主是在写 Templated Control 吧?

不过话说回来,楼主有必要自己去实现这个控件么? Silverlight Toolkit 中本身就有这样的控件啊,至少 2009年11月那个版本的 Toolkit 中就有,如

System.Windows.Controls.HeaderedItemsControl 是基类,Silverlight本身的类库中就有

<sdk:HeaderedItemsControl Margin="211,106,35,106" Height="88" Width="154">
<sdk:HeaderedItemsControl.Header>
<Button Content="Header is a button"></Button>
</sdk:HeaderedItemsControl.Header>
<Grid />
</sdk:HeaderedItemsControl>



<toolkit:HeaderedContentControl Margin="32,201,0,0" Width="120">
<toolkit:HeaderedContentControl.Header>
<Button Content="Header is a button"></Button>
</toolkit:HeaderedContentControl.Header>
<Grid />
</toolkit:HeaderedContentControl>



<toolkit:Expander Margin="8,8,0,0" Height="88" Width="154">
<toolkit:Expander.Header>
<Button Content="Header is a button"></Button>
</toolkit:Expander.Header>
<Grid />
</toolkit:Expander>



<toolkit:Accordion Margin="200,200,0,0" Height="88" Width="154">
<toolkit:AccordionItem>
<toolkit:AccordionItem.Header>
<Button Content="Header is a button"></Button>
</toolkit:AccordionItem.Header>
</toolkit:AccordionItem>
<Grid />
</toolkit:Accordion>


楼主如果是自己想实现类似的 Templated Control ,可以从 Toolkit 提供的Source 中去参考源代码,比如参考 Expander
daview 2010-05-11
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 websco 的回复:]
你在设置 HEADER = 某个UI 时,应保证这个UI不存在于可视化树中, 如果你的这个 UI对象是在 XAML 中生成的,那就应当先 Remove(),如果是通过代码 new 出来的,则没有这个问题。
[/Quote]

感谢!

该怎么REMOVE?我是在STYLE的SETTER里设置了这个HEADER的VALUE的。
pkjijie 2010-05-11
  • 打赏
  • 举报
回复
2——

在模板中设置一个HEADER对象的CONTENTCONTROL,其内容绑定到HEADER属性


绑定的问题吧。。。
websco 2010-05-10
  • 打赏
  • 举报
回复
你在设置 HEADER = 某个UI 时,应保证这个UI不存在于可视化树中, 如果你的这个 UI对象是在 XAML 中生成的,那就应当先 Remove(),如果是通过代码 new 出来的,则没有这个问题。

8,735

社区成员

发帖
与我相关
我的任务
社区描述
WPF/Silverlight相关讨论
社区管理员
  • WPF/Silverlight社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧