2013-12-11 35 views
3

場景:我有一系列定製UIElements(事實上,我已經替換了所有標準WPF FrameworkElements,我將使用更輕,更高效的對應件),以便僅使用這些系統的自定義佈局系統。他們都繼承了一個名爲Surface的類(它又是UIElement的直接後裔)。定製UIElement可以執行IList <UIElement>並直接分配給孩子(在XAML中)嗎?

我現在想知道如果我的Panel版本(姑且稱之爲SurfacePanel)可以簡單地實現IList<Surface>並允許直接添加到其子Surface元素,而不是一個Children屬性(如定期WPF面板),在XAML

爲了說明 - 在代碼隱藏,我現在能做的是:

SurfacePanel.Add(child); 

,並從,我希望能夠做到這一點XAML:

<SurfacePanel> 
    <child /> 
</SurfacePanel> 

但XAML似乎要求我有這樣的代碼隱藏模式:

SurfacePanel.Children.Add(child) 

(我並不真的需要這些控件支持XAML工作中運行時環境,但是在測試和原型設計時,我喜歡將我的UI控件設置爲「XAML友好」,這樣我就可以從VS中的可視化設計器(以及屬性窗格等)中受益,只要是「預覽」窗口)。

由於我的控制從UIElement繼承(並有適當的措施/整理/渲染覆蓋等),它們的功能相當不錯的時候穿上,也就是說,一個普通CanvasGrid。但VS XAML解析器對我的SurfacePanel(實現IList<Surface>不太滿意,當我在標記中添加子項時。它說「不能將內容添加到類型爲」SurfacePanel「的對象」「。

我知道,如果我添加一個合適類型的Children屬性並將其屬性添加到SurfaceCanvas類([ContentProperty("Children")]),它將起作用。但是由於SurfacePanel本身就是一個能夠實現相同目標的集合,有沒有辦法讓XAML「得到它」?


編輯:

我可以通過添加上簡單地返回其內ListSurfacePanel一個Children屬性,但然後添加和去除在該元件的直接旁路內部邏輯解決XAML遵守'將子元素連接起來。

如果內部列表是一個ObservableCollection,我能做到這一點的傳統方式,做一個CollectionChanged事件處理佈線 - 但基本上面板中集成IList整點直接是爲了避免..


編輯2:

這個 「作品」(但繞過接線):

[ContentProperty("Children")] 
public class SurfacePanel : Surface, IList<Surface> 
{ 
    private readonly List<Surface> _children = new List<Surface>(); 

    public List<Surface> Children 
    { 
     get { return _children; } 
    } 
} 

我無法回報this因爲SurfacePanel不是List<Surface>,而是IList<Surface>

如果我改變屬性

public IList<Surface> Children 
    { 
     get { return this; } 
    } 

我報復以下XAML的錯誤信息(但不與<m:SurfacePanel/>):

<m:SurfacePanel> 
</m:SurfacePanel> 

的錯誤消息是

Cannot set content property 'Children' on element 'SurfacePanel'. 'Children' has incorrect access level or its assembly does not allow access.

+0

這很奇怪,絕對沒有必要。你的CustomPanel本身不是一個List,它是其他'UIElements'的Parent元素,因此是'Children'集合。 –

+0

您的評論非常奇怪,絕對沒有必要。我的自定義面板是一個有孩子的容器(沒有別的),因此Panel.Add(child)是一個非常合乎邏輯的模式(並且要比通過一個額外的級別,即通過一個冗餘屬性更簡潔)。你可以說該面板是一個List的圖形表示。無論如何,問題不在於其他人是否能夠圍繞這種方法打頭陣,而是在XAML中是否可行。 – d7samurai

+0

你的評論實際上很奇怪,我想知道你怎麼看待XAML自己的語法來添加兒童[直接!]到一個面板。 – d7samurai

回答

3

同樣實施IList並聲明Children屬性是這樣的:

[ContentProperty("Children")] 
public class SurfacePanel : Surface, IList, IList<Surface> 
{ 
    public IList Children 
    { 
     get { return this; } 
    } 

    ... 
} 
+0

這很有效。不幸的是,它讓我的班級變得很醜陋,因爲除了IList 之外,還必須實施所有IList成員。這意味着我可以選擇在班級中擁有兩組每個成員,或者只是與馬虎的「IList」(用'object'操作 - blah)。既不吸引我,因爲我對這些事情有點肛門 - 我討厭黑客/不合理的解決方案,只是爲了讓事情「工作」。而這一切只是爲了讓XAML掌握一種本身正在使用的模式(即直接將小孩添加到面板中)。如果我只能讓它理解SurfacePanel是一個列表。 – d7samurai

+0

我想一個非常優雅的解決方案是遵循WPF設計模式,而不是直接實現IList ,而是隻有*有一個Children屬性。無論如何,您都會擁有該公共Children屬性,並且在沒有列表方法的情況下代碼會更少。把你的特殊收藏的東西放在一個內部的SurfaceCollection實現中(類似於UIElementCollection)。 – Clemens

+0

WPF FrameworkElement臃腫且效率低下,因爲它們非常通用。我所做的就是迴避它們和整個XAML範式。我的框架工作得很好 - 只有當我需要通過WPF和XAML交叉路徑時纔會出現這些問題。我的解決方案不適用於/不需要XAML,我設計的組件在_that_上下文中優雅,而不是用於XAML ..這只是因爲VS視覺設計師/ XAML編輯器作爲預覽工具很有幫助,而我正在開發,我甚至需要遵守。我討厭必須處理它。但謝謝你的幫助! – d7samurai

相關問題