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

发布于 2024-10-12 07:50:29 字数 2256 浏览 0 评论 0原文

我有一个自定义面板控件,我正在尝试在其中动态添加控件。当我运行应用程序时,静态和动态添加的控件完美显示,但动态控件不会出现在 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>

I have a custom panel control that I'm trying to dynamically add controls within. When I run the application the static and dynamically added controls show up perfectly, but the dynamic controls do not appear within the visual studio designer. Only the controls placed declaratively in the XAML appear. I'm currently adding the dynamic control in the CreateUIElementCollection override, but I've also tried this in the constructor without success.

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

And my usage of this custom panel

<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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吻泪 2024-10-19 07:50:29

我刚刚在 Visual Studio 2008 标准版中尝试了您的代码,面板显示在设计器中(请参见下面的屏幕截图)。

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>

I have just tried your code in Visual Studio 2008 Standard Edition and the Panel is showing up in the designer (see screen shot below).

alt text

The screenshot shows

Have you tried re-building your project, closing the XAML window and opening it again so that the designer can reload?

Edit: Just to clarify on the comment below, the button was added in XAML however if I remove the button this is the output I am getting in the Visual Studio designer.

alt text

This is the XAML I used to get this output:

<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>
难以启齿的温柔 2024-10-19 07:50:29

感谢本杰明给我的一些提示,我明白了。看起来您需要在 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

I figured it out thanks to some hints that Benjamin gave me. Looks like you need to load dynamically added controls in the UIElement.Loaded event handler. The designer apparently overwrites the values within the Children collection before this event occurs. Here's the code that fixed the issue:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文