2010-06-23 43 views
4

我想要創建一個WPF元素,該元素在運行時完全控制其子元素 - 在其屬性更改時添加和刪除子UI。有點像ItemsControl修改其ItemsSource屬性時所做的,儘管在我的情況下只有一個孩子。在運行時動態創建(封裝)子項的WPF元素

這將是MVVM的視圖容器 - 當您給它一個Model或ViewModel時,它會奇蹟般地創建正確的視圖並將所有東西連接起來。我的視圖容器不需要模板化(因爲它創建了用戶定義的視圖,這些視圖是UserControls並且有它們自己的模板),並且我希望它儘可能地封裝。我可能很容易做到這一點,從像Grid這樣的東西下降,並且當我自己的屬性改變時添加子控件;但Grid公開暴露了其子元素的集合,並允許任何人添加和刪除東西。

我應該從哪個WPF類中下載最大封裝,以及如何在運行時向它添加子元素?

基於我對文檔的理解,我嘗試使用FrameworkElement和AddVisualChild,只是爲了瞭解是否可以在運行時創建子控件。我不是在AddLogicalChild是否有必要清楚,但我把它放在以防萬一:

public class ViewContainer : FrameworkElement { 
    private TextBlock _child; 

    public ViewContainer() { 
     _child = new TextBlock { Text = "ViewContainer" }; 
     AddLogicalChild(_child); 
     AddVisualChild(_child); 
     InvalidateMeasure(); 
    } 

    public object Content { get; set; } 

    protected override Size ArrangeOverride(Size finalSize) { 
     _child.Arrange(new Rect(finalSize)); 
     return finalSize; 
    } 
    protected override Size MeasureOverride(Size availableSize) { 
     _child.Measure(availableSize); 
     return _child.DesiredSize; 
    } 
} 

當我把一個ViewContainer到窗口,並運行此,我希望看到一個TextBlock說「ViewContainer 」。但是,我只是看到一個空白的窗口。所以顯然我錯過了一些東西。

我該如何修正上面的代碼,以便「運行時」出現「子」控件,但不會暴露給其他人混淆(任何情況下都可以避免)?

回答

6

要回答您的具體問題,您還需要覆蓋GetVisualChildVisualChildrenCount屬性以使您的子元素能夠顯示。

+0

很酷 - 做到了。雖然我有點困惑,爲什麼有一個AddVisualChild,如果它實際上並沒有將*添加到*任何東西。 – 2010-06-24 00:15:33

+1

啊,我明白了。它讓孩子知道其父母;但許多家長不需要兒童名單(沒有或只有一個兒童),因此它將選擇和責任留給父母。關注點的積極分離:我非常喜歡WPF的一件事。但這意味着名稱「AddVisualChild」是誤導性的,因爲它表明它將它添加到某種列表中,而不是。 – 2010-06-24 11:50:53

0

您是否想過利用WPF對隱式DataTemplates的支持?

我已經處理了一個類似於你的要求的方式是使用ContentControl。我將Content屬性綁定到我的ViewModel。然後確保在ContentControl上方的樹中某處引用的資源字典中,我爲所有可能分配給內容屬性的ViewModel類型定義了DataTemplates。

這種方式WPF負責爲我的ViewModel接線正確的視圖。

+0

是的,我以前做過這個,但是這次我想更進一步 - 我希望我的ViewContainer能夠採用一個模型,並自動發現並創建適合它的ViewModel,並從那裏到視圖。我不認爲DataTemplate.DataType會在沒有幫助的情況下讓我到那裏。 – 2010-06-24 00:11:33

+0

當然,DataTemplate.DataType不適合,但有DataTemplateSelector可能。 – 2015-11-03 11:56:19