【问题标题】:wpf - Binding issue ActualWidthwpf - 绑定问题 ActualWidth
【发布时间】:2013-08-09 06:33:05
【问题描述】:

我有以下 XAML 代码:

<Grid Grid.Row="2" Name="grid_StatusBar">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="{Binding ElementName=wrapPanel, Path=ActualWidth}" />
        <ColumnDefinition Width="30" />
    </Grid.ColumnDefinitions>
    <ProgressBar Grid.Column="0" HorizontalAlignment="Stretch" Margin="5,5,5,5" Name="progressBar1" VerticalAlignment="Stretch" />
    <WrapPanel Grid.Column="1" Name="wrapPanel" HorizontalAlignment="Right">
        <Label Content="1" Height="28" HorizontalAlignment="Right" Margin="0,0,0,0" Name="label_Dataset" VerticalAlignment="Stretch" Visibility="Collapsed" />
        <Label Content="/20" Height="28" HorizontalAlignment="Right" Margin="0,0,0,0" Name="label_TotalDatasets" VerticalAlignment="Stretch" Visibility="Collapsed" />
        <Label Content="ID:" Height="28" HorizontalAlignment="Right" Margin="0,0,0,0" Name="label_IDText" VerticalAlignment="Stretch" />
        <Label Content="no id" Height="28" HorizontalAlignment="Right" Margin="0,0,0,0" Name="labelID" VerticalAlignment="Stretch" />
    </WrapPanel>
    <Button Grid.Column="2" Name="button_Help" Height="30" Width="30" Content="?" HorizontalAlignment="Right" VerticalAlignment="Stretch" Click="button_Help_Click" >
</Grid>

我试图在更改某些标签的可见性并设置不同的文本(因此不同的长度/宽度)时尽可能宽地显示进度条。

然后我有不同的功能:

  • 在程序启动时,labelID 标签的“no id”文本被替换为内部值。 宽度已更新OK
  • 随着代码的运行,我更改了前两个标签的可见性,ColumnDefinition.Width 没有更新,只显示前两个标签(因为没有足够的位置让所有 4 个标签都适合wrapPanel 实际宽度:错误!
  • 如果我将Visibility 属性从前两个标签从Collapsed 更改为Visible,从一开始所有标签的可见性都是Visible,并且所有标签都会显示:OK
  • 从之前的状态,我将前两个标签的可见性更改为 CollapsedColumnDefinition.Width 被更新,ProgressBar 尽可能宽,所有文本都显示:OK

谁能帮帮我?不明白为什么不更新宽度...

注意:使用运行以下代码的窗口中的两个按钮更改可见性:

label_Dataset.Visibility = System.Windows.Visibility.Visible;
label_TotalDatasets.Visibility = System.Windows.Visibility.Visible;

编辑:我的目标是使用最小空间(一行)显示可见标签,以便让 ProgressBar 使用可能的最大宽度。

【问题讨论】:

  • 设置列宽为Auto 试试看。

标签: wpf binding actualwidth


【解决方案1】:

无法根据子元素的宽度更改父元素的宽度。在您的情况下,该列是WrapPanel 的父级,因此WrapPanelActualWidth 在网格/列已经调整大小之前不可用。

即使您编写代码来尝试规避这一点,您仍然会遇到问题,因为度量/布局序列会变得可重入。每当列的大小发生变化时,它都会重新布局所有子控件,其中之一是WrapPanel。这将导致WrapPanelActualWidth 被更改——有效地导致无限循环。为了防止这种堆栈溢出情况,框架会立即检测布局/测量周期中的任何重入并抛出异常。

我不确定您要达到的目标。为什么你想要WrapPanel 中的标签?当然,您总是希望 4 个标签位于同一行,或者至少位于两行。

如果是这种情况,我会将第二列的宽度设置为“自动”并将标签放在另一个容器中,即以下容器之一:

  • 如果您希望所有标签都换行,例如 WrapPanel 被强制为最小宽度,请使用:

    <StackPanel Grid.Column="1" Orientation="Vertical">
        ... your labels here ...
    </StackPanel>
    
  • 如果您希望所有标签保持在同一行,请使用:

    <StackPanel Grid.Column="1" Orientation="Horizontal">
        ... your labels here ...
    </StackPanel>
    
  • 如果你想要两行使用:

    <StackPanel Grid.Column="1" Orientation="Vertical">
        <StackPanel Orientation="Horizontal">
            ... 1st 2 labels here  ...
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            ... 2nd 2 labels here  ...
        </StackPanel>
    </StackPanel>
    

【讨论】:

  • 嗨@Peter,谢谢!它可以将其更改为 StackPanel。我只是想使用最小空间(在一行中)显示可见标签,以便让 ProgressBar 使用可能的最大宽度。我刚刚将WrapPanel 更改为StackPanel 并将ColumnDefinition 宽度更改为Auto,它的显示就像我想要的那样......再次感谢!
  • “不可能根据子元素的宽度来改变父元素的宽度”:我认为Canvas 面板是这个一般规则的一个例外,但仅仅是因为它没有'不要根据其子级调整自身大小。
猜你喜欢
  • 2011-11-16
  • 2010-12-09
  • 1970-01-01
相关资源
最近更新 更多