WPF 元素与动态生成的 UI 元素绑定

发布于 2024-09-17 18:00:30 字数 2325 浏览 2 评论 0原文

我有一个页面,其中有一个包含 2 列的网格,一列可容纳 80* 宽度,另一列可容纳 20* 宽度。网格下方是一个堆栈面板,我在运行时向其中加载 UI 元素(子堆栈面板)。

我的目标是将堆栈面板的宽度绑定到网格的列。如果动态内容在设计视图中被模拟为静态,则效果非常好,并且堆栈面板会调整大小。但是当应用程序运行时,绑定失败并且宽度未绑定。

有什么方法可以刷新绑定,以便我可以通知堆栈面板引用网格的宽度并配置其大小?

更新: 这就是我的 XAML 的样子:

<Page x:Class="WPFTestApp.Page1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Page1">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Grid x:Name="resizeGrid"
              Grid.Column="0" Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition x:Name="leftColumn"
                                  Width="80*" />
                <ColumnDefinition x:Name="rightColumn"
                                  Width="20*" />
            </Grid.ColumnDefinitions>            
        </Grid>

        <StackPanel x:Name="contentPanel"
                    Grid.Column="0" Grid.Row="0" >
            <!-- Dynamic StackPanels are added here -->
        </StackPanel>
    </Grid>
</Page>

在我的代码中,我创建 StackPanel 元素并将其添加到 contentPanel 中,方法是: contentPanel.Children.Add(...);

不幸的是,我必须在这里使用 StackPanels。 :-(

动态创建的 StackPanel 元素的标记如下(请注意,我使用了 XAML 中已有的绑定到网格):

<StackPanel x:Name="element01"
             Orientation="Horizontal"
             Width="{Binding ElementName=resizeGrid, Path=ActualWidth}" >
    <StackPanel x:Name="leftPanel"
                Orientation="Vertical"
                Width="{Binding ElementName=leftColumn, Path=ActualWidth}">
        <!-- Content goes here -->
    </StackPanel>
    <StackPanel x:Name="rightPanel"
                Orientation="Vertical"
                Width="{Binding ElementName=rightColumn, Path=ActualWidth}">
        <!-- Content goes here -->
    </StackPanel>
</StackPanel>

我的动态 StackPanel 元素的 XAML 代码是通过 XSLT 转换生成的,

请注意 xmlns:x 命名空间动态 StackPanel 也必须完成,因为它是通过 XSLT 生成的。

I have a page in which I have a grid with 2 columns, one accommodating 80* width and the other accommodating 20*. Beneath the grid is a stack panel to which I load UI elements (child stack panels) at runtime.

My objective is to bind the widths of the stackpanels to the columns of the grid. This works perfectly and the stackpenels resize if the dynamic content is mocked to be static in the design view. But when the application is run, the bindings fail and the widths are not bound.

Is there any way to refresh the bindings so that I can notify the stackpanels to refer the widths of the grid and configure its's size?

Updated:
This is what my XAML looks like:

<Page x:Class="WPFTestApp.Page1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Page1">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Grid x:Name="resizeGrid"
              Grid.Column="0" Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition x:Name="leftColumn"
                                  Width="80*" />
                <ColumnDefinition x:Name="rightColumn"
                                  Width="20*" />
            </Grid.ColumnDefinitions>            
        </Grid>

        <StackPanel x:Name="contentPanel"
                    Grid.Column="0" Grid.Row="0" >
            <!-- Dynamic StackPanels are added here -->
        </StackPanel>
    </Grid>
</Page>

In my code, I create StackPanel elements and add it to the contentPanel by saying:
contentPanel.Children.Add(...);

Unfortunately, I HAVE to use StackPanels here. :-(

The markup of a dynamically created StackPanel element is as follows (note that I use a Binding to the grid already in the XAML):

<StackPanel x:Name="element01"
             Orientation="Horizontal"
             Width="{Binding ElementName=resizeGrid, Path=ActualWidth}" >
    <StackPanel x:Name="leftPanel"
                Orientation="Vertical"
                Width="{Binding ElementName=leftColumn, Path=ActualWidth}">
        <!-- Content goes here -->
    </StackPanel>
    <StackPanel x:Name="rightPanel"
                Orientation="Vertical"
                Width="{Binding ElementName=rightColumn, Path=ActualWidth}">
        <!-- Content goes here -->
    </StackPanel>
</StackPanel>

The XAML code for my dynamic StackPanel elements are generated through an XSLT transformation

Note the xmlns:x namespace dynamic StackPanel. This also has to be done because of it being generated through XSLT

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

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

发布评论

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

评论(3

江挽川 2024-09-24 18:00:30

据我所知,使用 Orientation="Horizo​​ntal" 设置 StackPanelWidth 不会产生任何效果。 StackPanel 的大小不超过其内容在其方向上的大小。

为什么你“必须”在这里使用StackPanel?考虑到您的目标,您几乎肯定需要 DockPanel。您无需绑定或设置任何内容,因为 DockPanel 会自动填充单元格。

As far as I know setting the Width of a StackPanel with Orientation="Horizontal" will have no effect. The size of a StackPanel does not exceed the size of its content in its oriented direction.

Why do you "HAVE" to use StackPanels here? You almost certainly want DockPanels, given your objective. You won't have to bind or set anything, because the DockPanel will fill the cell automatically.

西瑶 2024-09-24 18:00:30

尝试绑定 ActualWidth 而不是 Width。

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <Grid x:Name="resizeGrid"
          Grid.Column="0" Grid.Row="0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition x:Name="leftColumn"
                              Width="{Binding ElementName=contentPanel, Path=ActualWidth}" />
            <ColumnDefinition x:Name="rightColumn"
                              Width="*" />
        </Grid.ColumnDefinitions>
    </Grid>       


    <StackPanel x:Name="contentPanel"
                Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" >
        <StackPanel Background="Yellow" Width="100" Height="25" />
        <StackPanel Background="Green" Width="120" Height="25" />
        <StackPanel Background="Red" Width="140" Height="25" />
        <TextBlock Background="Gray" Text="{Binding ElementName=contentPanel, Path=ActualWidth}" />
    </StackPanel>
</Grid>

我在上面做了以下更改:
1) 将leftColumn设置为contentPanelActualWidth
2) 将 rightColumn 设置为 *
3) contentPanel Horizo​​ntalAlignment 应更改为 Stretch 以外的值。这里我把它改成了Left

HTH

Try binding the ActualWidth instead of Width.

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <Grid x:Name="resizeGrid"
          Grid.Column="0" Grid.Row="0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition x:Name="leftColumn"
                              Width="{Binding ElementName=contentPanel, Path=ActualWidth}" />
            <ColumnDefinition x:Name="rightColumn"
                              Width="*" />
        </Grid.ColumnDefinitions>
    </Grid>       


    <StackPanel x:Name="contentPanel"
                Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" >
        <StackPanel Background="Yellow" Width="100" Height="25" />
        <StackPanel Background="Green" Width="120" Height="25" />
        <StackPanel Background="Red" Width="140" Height="25" />
        <TextBlock Background="Gray" Text="{Binding ElementName=contentPanel, Path=ActualWidth}" />
    </StackPanel>
</Grid>

The following changes I have done above:
1) Set the leftColumn to the ActualWidth of the contentPanel
2) Set the rightColumn to *
3) contentPanel HorizontalAlignment should be changed other then Stretch. Here I have changed it to Left

HTH

深爱不及久伴 2024-09-24 18:00:30

我找到了这个问题的解决方案。 (抱歉回复晚了)

我所做的是将“resizeGrid”网格控件剪切并粘贴到“contentPanel”堆栈面板中。

正如我上面提到的,contentPanel 中的内容是通过 XSLT 转换生成的,这肯定会产生命名空间引用问题。我注意到每当加载此窗口时,输出窗口中都会出现“未找到元素...”消息 - 这证明我是对的。

将“resizeGrid”插入“contentPanel”会有所帮助,因为两个控件都位于同一命名空间内,并且可以使用“ElementName”属性引用 PropertyBinding。

感谢您的支持! :-)

I found a solution for this issue. (Sorry for the late response)

What I did was, I cut and pasted the "resizeGrid" Grid control into the "contentPanel" Stackpanel.

As I mentioned above, the contents within the contentPanel are generated through an XSLT transformation and this surely creates a namespace reference issue. I noticed "element not found..." message in the Output window whenever this Window is loaded - this proved me right.

Inserting the "resizeGrid" into the "contentPanel" helped because then both the controls are within the same namespace and can be referenced for a PropertyBinding using "ElementName" attribute.

Thank you for your support! :-)

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