WPF 4.0自定义面板不会在VS 2010 Designer中显示动态添加的控件

时间:2011-01-17 19:30:56

标签: wpf visual-studio-2010 wpf-controls designer

我有一个自定义面板控件,我正在尝试动态添加控件。当我运行应用程序时,静态和动态添加的控件显示完美,但动态控件不会出现在visual studio设计器中。仅出现在XAML中以声明方式放置的控件。我目前正在CreateUIElementCollection覆盖中添加动态控件,但我也在构造函数中尝试了这个但没有成功。

Public Class CustomPanel1
Inherits Panel

Public Sub New()

End Sub

Protected Overrides Function MeasureOverride(ByVal availableSize As System.Windows.Size) As System.Windows.Size
    Dim returnValue As New Size(0, 0)

    For Each child As UIElement In Children
        child.Measure(availableSize)
        returnValue.Width = Math.Max(returnValue.Width, child.DesiredSize.Width)
        returnValue.Height = Math.Max(returnValue.Height, child.DesiredSize.Height)
    Next

    returnValue.Width = If(Double.IsPositiveInfinity(availableSize.Width), returnValue.Width, availableSize.Width)
    returnValue.Height = If(Double.IsPositiveInfinity(availableSize.Height), returnValue.Height, availableSize.Height)

    Return returnValue
End Function

Protected Overrides Function ArrangeOverride(ByVal finalSize As System.Windows.Size) As System.Windows.Size
    Dim currentHeight As Integer
    For Each child As UIElement In Children
        child.Arrange(New Rect(0, currentHeight, child.DesiredSize.Width, child.DesiredSize.Height))
        currentHeight += child.DesiredSize.Height
    Next

    Return finalSize
End Function

Protected Overrides Function CreateUIElementCollection(ByVal logicalParent As System.Windows.FrameworkElement) As System.Windows.Controls.UIElementCollection
    Dim returnValue As UIElementCollection = MyBase.CreateUIElementCollection(logicalParent)

    returnValue.Add(New TextBlock With {.Text = "Hello, World!"})

    Return returnValue
End Function

Protected Overrides Sub OnPropertyChanged(ByVal e As System.Windows.DependencyPropertyChangedEventArgs)
    MyBase.OnPropertyChanged(e)
End Sub
End Class

我对这个自定义面板的使用

<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:CustomPanel"
Title="MainWindow" Height="364" Width="434">

<local:CustomPanel1>
    <CheckBox />
    <RadioButton />
</local:CustomPanel1>

</Window>

2 个答案:

答案 0 :(得分:1)

我刚刚在Visual Studio 2008 Standard Edition中尝试过您的代码,而Panel正在设计器中显示(参见下面的屏幕截图)。

alt text

屏幕截图显示

您是否尝试重新构建项目,关闭XAML窗口并再次打开它以便设计人员可以重新加载?

编辑:为了澄清下面的评论,该按钮已在XAML中添加,但如果我删除该按钮,则这是我在Visual Studio设计器中获得的输出。

alt text

这是我用来获得此输出的XAML:

<Window x:Class="Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="Window1" Height="300" Width="300">
    <local:CustomPanel1>

    </local:CustomPanel1>
</Window>

答案 1 :(得分:1)

由于本杰明给我的一些暗示,我想通了。看起来您需要在UIElement.Loaded事件处理程序中加载动态添加的控件。在此事件发生之前,设计者显然会覆盖Children集合中的值。这是解决问题的代码:

Public Class CustomPanel1
Inherits Panel

Private _text As TextBlock

Public Sub New()

End Sub

Protected Overrides Function MeasureOverride(ByVal availableSize As System.Windows.Size) As System.Windows.Size
    Dim returnValue As New Size(availableSize.Width, availableSize.Height)
    If _text IsNot Nothing Then


        For Each child As UIElement In Children
            child.Measure(availableSize)
            returnValue.Width = Math.Max(returnValue.Width, child.DesiredSize.Width)
            returnValue.Height = Math.Max(returnValue.Height, child.DesiredSize.Height)
        Next

        returnValue.Width = If(Double.IsPositiveInfinity(availableSize.Width), returnValue.Width, availableSize.Width)
        returnValue.Height = If(Double.IsPositiveInfinity(availableSize.Height), returnValue.Height, availableSize.Height)
    End If
    Return returnValue
End Function

Protected Overrides Function ArrangeOverride(ByVal finalSize As System.Windows.Size) As System.Windows.Size
    If _text IsNot Nothing Then
        Dim currentHeight As Integer
        For Each child As UIElement In Children
            child.Arrange(New Rect(0, currentHeight, child.DesiredSize.Width, child.DesiredSize.Height))
            currentHeight += child.DesiredSize.Height
        Next
    End If

    Return finalSize
End Function

Private Sub CustomPanel1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
    _text = New TextBlock With {.Text = "Hello, World!"}
    Children.Add(_text)
End Sub
End Class