WPF 将控制保持在完美的矩形形状(绑定宽度和高度)

发布于 2024-10-13 08:21:09 字数 2874 浏览 6 评论 0原文

目前,我正在努力让控件在 WPF 中以框形状显示,而无需将结果写入代码。这是我希望它看起来像的一个工作示例:

  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="120"/>
      <RowDefinition Height="3" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal">
      <Button Margin="6" VerticalAlignment="Stretch" Width="{Binding Path=ActualHeight, Mode=OneWay, RelativeSource={RelativeSource Self}}">
        <Grid>
          <Grid.RowDefinitions>
           <RowDefinition Height="*" />
           <RowDefinition Height="Auto" />
          </Grid.RowDefinitions>
          <Image Source="http://blog.joeclarmusic.com/images/rss-icon.jpg" />
          <TextBlock Foreground="Black" TextAlignment="Center" Grid.Row="1" FontSize="11" Text="{Binding Path=Name}" Margin="0, 5, 0, 0" HorizontalAlignment="Center" TextWrapping="Wrap" />
        </Grid>
      </Button>
    </StackPanel>
    <GridSplitter Grid.Row="1" Background="#DDDDDD" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
  </Grid>

好的,这一切都很酷而且很好。在我当前的设计中,我使用 ItemsControl 并显示图像列表。由于这样的列表可能超出窗口的宽度,因此我想在禁用 VerticalScrollBar 的 StackPanel 周围添加 ScrollViewer(因为我只希望它从左向右流动,所以我只需要 Horizo​​ntalScrollBar)。

添加 ScrollViewer 后:

  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="120"/>
      <RowDefinition Height="3" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <ScrollViewer>
      <StackPanel Orientation="Horizontal">
        <Button Margin="6" VerticalAlignment="Stretch" Width="{Binding Path=ActualHeight, Mode=OneWay, RelativeSource={RelativeSource Self}}">
          <Grid>
          <Grid.RowDefinitions>
           <RowDefinition Height="*" />
           <RowDefinition Height="Auto" />
          </Grid.RowDefinitions>
          <Image Source="http://blog.joeclarmusic.com/images/rss-icon.jpg" />
          <TextBlock Foreground="Black" TextAlignment="Center" Grid.Row="1" FontSize="11" Text="{Binding Path=Name}" Margin="0, 5, 0, 0" HorizontalAlignment="Center" TextWrapping="Wrap" />
         </Grid>    
        </Button>
      </StackPanel>
    </ScrollViewer>
    <GridSplitter Grid.Row="1" Background="#DDDDDD" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
  </Grid>

在我的计算机中的 kaxaml 1.7.1 中运行时的上述图像: jonatan.nilsson.is/wpf_with_scrollviewer.jpg

如果您在 Kaxaml(或 WPF 窗口/页面)中运行它,您的 按钮现在将继续变得越来越大(宽度和高度)。我所做的唯一更改是在 StackPanel 周围添加 ScrollViewer。其他一切都是一样的,那么为什么它在滚动查看器中不断变大呢?

我在这里做错了什么?

编辑: 添加了第二个示例的结果图像。

Currently I am struggling to get a control to be displayed in a box shape in WPF without having to need to result to code. Here is a working example of what I want it to look like:

  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="120"/>
      <RowDefinition Height="3" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal">
      <Button Margin="6" VerticalAlignment="Stretch" Width="{Binding Path=ActualHeight, Mode=OneWay, RelativeSource={RelativeSource Self}}">
        <Grid>
          <Grid.RowDefinitions>
           <RowDefinition Height="*" />
           <RowDefinition Height="Auto" />
          </Grid.RowDefinitions>
          <Image Source="http://blog.joeclarmusic.com/images/rss-icon.jpg" />
          <TextBlock Foreground="Black" TextAlignment="Center" Grid.Row="1" FontSize="11" Text="{Binding Path=Name}" Margin="0, 5, 0, 0" HorizontalAlignment="Center" TextWrapping="Wrap" />
        </Grid>
      </Button>
    </StackPanel>
    <GridSplitter Grid.Row="1" Background="#DDDDDD" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
  </Grid>

Ok, this is all cool and well. In my current design, I am using ItemsControl and displaying a list of images. Since such a list can exceed the width of the window I wanted to add ScrollViewer around the StackPanel where the VerticalScrollBar is disabled (since I only want it to flow from left to right, I only need the HorizontalScrollBar).

After adding the ScrollViewer:

  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="120"/>
      <RowDefinition Height="3" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <ScrollViewer>
      <StackPanel Orientation="Horizontal">
        <Button Margin="6" VerticalAlignment="Stretch" Width="{Binding Path=ActualHeight, Mode=OneWay, RelativeSource={RelativeSource Self}}">
          <Grid>
          <Grid.RowDefinitions>
           <RowDefinition Height="*" />
           <RowDefinition Height="Auto" />
          </Grid.RowDefinitions>
          <Image Source="http://blog.joeclarmusic.com/images/rss-icon.jpg" />
          <TextBlock Foreground="Black" TextAlignment="Center" Grid.Row="1" FontSize="11" Text="{Binding Path=Name}" Margin="0, 5, 0, 0" HorizontalAlignment="Center" TextWrapping="Wrap" />
         </Grid>    
        </Button>
      </StackPanel>
    </ScrollViewer>
    <GridSplitter Grid.Row="1" Background="#DDDDDD" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
  </Grid>

Image of the above when running in kaxaml 1.7.1 in my computer: jonatan.nilsson.is/wpf_with_scrollviewer.jpg

If you run it in Kaxaml (or in a WPF window/page) your button will now keep on getting bigger and bigger (both width and height). The only change I have done is add ScrollViewer around the StackPanel. everything else is the same so why does it keep on getting bigger when inside a scrollviewer?

What am I doing wrong here?

Edit:
Added an image of the outcome from the second example.

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

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

发布评论

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

评论(2

以可爱出名 2024-10-20 08:21:09

好的,我找到了解决方案。如果满足以下条件,则会发生此“行为”:

  • 按钮的内容包含图像
  • 宽度/高度与其高度/宽度绑定。
  • 按钮内容高于其宽度(当绑定设置为高度->宽度时)

您可以很容易地测试这一点。如果删除 Button.Content 中除图像之外的所有内容,则整个内容“几乎”有效(如果使用 GridSplitter 使行高变小,按钮不会变小,但它会变大)。

但是,如果您随后将 Margin="0, 0, 0, 1" 添加到图像,则会发生与之前相同的行为(即,它无限增长)。

发生的情况基本上是这样的:

  1. 按钮高度高于其宽度。
  2. 绑定看到它并使其变宽
  3. 图像看到它变宽并使其自身更高以保持其比例(在本例中为 1:1)
  4. 图像将自身推得更高。
  5. 按钮高度高于其宽度,请转到步骤 2。

基本上,因为图像的行为是始终保持其比例。要解决此“行为”,就是使按钮内容的宽度大于高度。如果按钮内容的宽度高于其高度,则绑定将强制其宽度降低。这在某种程度上使图像表现正确。

在我的第二个示例中,添加例如:

Margin="30 ,0" 

To Image 将解决其永无休止的增长问题。

我不确定我是否解释得很好,所以如果您有可能改进此解释的建议,请发表评论。

Ok, I found a solution. This "behavior" occurs if the following condition are met:

  • The content of the button contains an image
  • The width/height has binding to it's height/width.
  • The button content is higher than it's width (when the binding is set to height->width)

You can test this very easily. If you remove everything inside the Button.Content except for the image, the whole thing "almost" works (the button will not become smaller if you make the row height smaller using the GridSplitter but it will grow bigger).

However if you then add Margin="0, 0, 0, 1" to the Image, then the same behavior occurs as before (that is, it grows infinitely).

What is happening is basically this:

  1. Button height is higher than it's width.
  2. Binding sees it and makes it wider
  3. The Image sees it's gotten wider and makes itself higher in order to keep it's ratio (in this case 1:1)
  4. The Image pushes itself higher.
  5. The Button height is higher than it's width, go to step 2.

Basically, because the behavior of the image is to always keep it's ratio. To work around this "behavior" is to make the Button content's be wider than it is in height. If the Button contents width is higher than it's height, then the Binding will force it's width lower. This somehow makes the image behave correctly.

In my second example, adding for example this:

Margin="30 ,0" 

To Image will fix the issue of it's never-ending growth.

I'm not sure if I explained this very well so please comment if you have suggestions that might improve this explanation.

淡看悲欢离合 2024-10-20 08:21:09

编辑:
好的,我稍微修改了一下你的代码,我可以确认按钮确实变得无限大。我真的无法说出为什么会发生这种情况。可能某些内部测量已经变得无聊了。我确实发现使用任何面板控件作为按钮内容(在本例中为网格)都会导致问题,StackPanel 或 DockPanel 等也会导致问题。也许您最好不要将这些项目放在按钮中,而是使用其他控件。它真的需要一个按钮吗?

旧:
按钮的高度不断变大,可能是因为网格单元本身不断变大。如果您使用网格分割器来调整网格组件的大小,那么该按钮将呈现其所在单元格的整个高度。如果您要解释它“不断变大”的情况,也许会更有意义想想看,如果这是要驻留在项目控件中的东西,为什么首先要使用网格拆分器和空单元格?

较旧的:
我认为“现在将溢出,高度会变得越来越大”,我认为您指的是按钮的宽度和高度。那是因为宽度直接与高度绑定。

如果您的意思是“不会溢出......”,那么这是另一个故事,完全与网格行的大小有关。也许您应该澄清您的实际问题是什么,并且也许提供一些有效的 XAML 作为示例。 (您帖子中的 XAML 按钮内容中缺少 '' 标记。

EDIT:
OK, I have fiddled with your code a bit, and I can confirm that the button is indeed growing infinitely large. I can't really say why this is happening. Probably some internal measurement is getting borked. I did find that using any panel control as the button content (Grid in this case) will cause the problem, as will a StackPanel or DockPanel and so on. Perhaps you would be better off by not putting these items in a button, and use some other control instead. Does it really need to be a button?

OLD:
The height of the button keeps getting bigger, probably because the grid cell itself keeps getting bigger. If you use the grid splitter to resize the grid components, then the button will assume the entire height of the cell that it resides in. Maybe it would make more sense if you were to explain the circumstances under which it 'keeps getting bigger' Come to think of it, if this is something that is to reside in an items control, why the grid splitter and empty cell in the first place?

OLDER:
By 'will now overflow the height keep getting bigger' I assume that you mean the width as well as the height of your button. Well that is because you have the width bound directly to the height.

If you mean 'will NOT overflow....' well that is another story altogether having to do with the size of your grid rows. Perhaps you should clarify what your actual problem is, and maybe provide some valid XAML as an example. (The XAML in your post is missing a '' tag in the button content.

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