【问题标题】:How to avoid having a Window smaller than the minimum size of a UserControl in WPF?如何避免窗口小于 WPF 中 UserControl 的最小大小?
【发布时间】:2012-03-08 07:42:53
【问题描述】:

我有一个用户控件(状态栏),它有一个隐式的最小尺寸(不是通过属性设置的,我的意思是当它达到最小尺寸时,它不能被缩小并被裁剪)。

有没有办法让主窗口知道 UserControl 将被裁剪并且不允许它减小其大小?有了像 WPF 这样的智能布局系统,它必须是一种知道它正在裁剪事物的方式。看下一张图片:

【问题讨论】:

  • 您使用什么类型的布局容器(流等)?
  • 我实际上正在使用堆栈面板,但我可以使用任何我需要的东西来实现我的目标。
  • 您的问题是否得到了解决?
  • 一点也不。老实说,我觉得这非常令人沮丧,因为这对我来说很明显。如果你成功了,请回来。
  • @IgnacioSolerGarcia 这个问题解决了吗?

标签: .net wpf size resize


【解决方案1】:

我知道我来晚了,但我想说我已经找到了解决这个问题的几乎最干净的解决方案。

1.) 创建一个自定义 UserControl(如果您正在使用)

public class ExtendedUserControl : UserControl
{
    public static readonly RoutedEvent ContentChangedEvent
    = EventManager.RegisterRoutedEvent(
        "ContentChanged",
        RoutingStrategy.Bubble,
        typeof(RoutedEventHandler),
        typeof(ExtendedUserControl));

    public event RoutedEventHandler ContentChanged
    {
        add { AddHandler(ContentChangedEvent, value); }
        remove { RemoveHandler(ContentChangedEvent, value); }
    }

    protected override void OnContentChanged(object oldContent, object newContent)
    {
        base.OnContentChanged(oldContent, newContent);
        RaiseEvent(new RoutedEventArgs(ContentChangedEvent, this));
    }
}

2.) 将事件附加到您的用户控件

<extended:ExtendedUserControl Height="auto" Width="auto" cal:View.Model="{Binding CurrentModel}" ContentChanged="ExtendedUserControl_ContentChanged"/>

3.) 已更新现在我们来到解决方案的最后一部分。

private void ExtendedUserControl_ContentChanged(object sender, System.Windows.RoutedEventArgs e)
    {
        Thread task = new Thread(() =>
        {
            Dispatcher.Invoke(() =>
            {
                SizeToContent = SizeToContent.WidthAndHeight;
                MinHeight = Height;
                MinWidth = Width;
            });
        });
        task.Start();
    }

干杯

【讨论】:

  • 我不再使用 WPF,但我记得有类似 Rendered 事件。你可以检查一下。
  • 刚刚检查了这个,我找不到 UserControl 或控件本身的任何事件。此外,我正在使用 MVVM,据我所知,视图是在创建绑定之前加载的。此外,我似乎只有一些 xaml 错误,因为我现在能够删除线程睡眠,到目前为止没有任何问题
【解决方案2】:

我知道这是事后几年的事了,但我最近遇到了这个问题,因为我正在处理我遇到的类似问题。这就是我解决它的方法。该解决方案是针对我的问题的,但可以进行更改以获得各种所需的调整大小行为。

首先设置窗口,使其最初调整大小以适应其内容。

<Window ...
    SizeToContent="WidthAndHeight" >

接下来我设置每个嵌入式控件,以便它报告所需的宽度和高度。大多数内置控件都会为您执行此操作。您可以通过覆盖 MeasureOverride 来为自定义控件执行此操作,或者您可以为控件设置宽度和高度。将此设置为您希望控件获得的最小尺寸。

<MyControl Name="_MyControlName" Width="640" Height="480" />

不必担心这些“硬”编码值会影响控件的行为。我们接下来处理这个问题。现在,当窗口显示时,它会自动调整以适应您的控件。

接下来订阅窗口加载事件。

<Window ...
    SizeToContent="WidthAndHeight" Loaded="Window_Loaded" >

在窗口加载事件中,您可以调整窗口的大小行为和其中的控件。您可以制作它,以便您的控件可以调整大小。您可以将窗口的最小尺寸设置为您刚刚布置的尺寸。这里的好处是你只允许布局系统为你找到一个好的布局。你想利用它的工作。

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        // We know longer need to size to the contents.
        ClearValue(SizeToContentProperty);
        // We want our control to shrink/expand with the window.
        _MyControlName.ClearValue(WidthProperty);
        _MyControlName.ClearValue(HeightProperty);
        // Don't want our window to be able to get any smaller than this.
        SetValue(MinWidthProperty, this.Width);
        SetValue(MinHeightProperty, this.Height);
    }

您在 Window_Loaded 方法中放置的内容将取决于您尝试完成的行为。

希望这可以帮助其他人节省时间。

【讨论】:

  • Mmmm ...我在这里担心的是您的初始布局基于固定尺寸,这可能是错误的并导致错误的初始布局。那你会怎么处理呢?
  • 这可能是个问题。然而,它并不适合我。内置控件(标签、按钮等)通常可以很好地报告准确的大小,我们的自定义控件也可以(通过覆盖 MeasureOverride 和 ArrangeOverride)。对于那些表现不佳的人,您可以在 XAML 中设置合适的宽度/高度,甚至可以根据控件将提前显示的数据来计算它 - 然后通过代码隐藏或数据绑定进行设置。在我使用的示例中,我有一个视频控件在这方面做得很差,所以我在显示之前设置了大小以匹配视频流 (640x480)。
  • 再次您好,我实际上是在谈论不同的 DPI 设置、不同的文本大小设置、可能使固定大小出现问题的那种事情,您是否尝试过使用不同 DPI 的应用程序?
  • 您可能偶尔需要考虑到这一点。实际上对我来说这不是问题。当 WPF 执行“内容大小”时,它会为您考虑这些内容。通常自定义样式控件是建立在其他组件之上的,其中许多已经考虑到了这一点。如果您确实需要固定数量的物理像素,您可能需要提供计算出的尺寸,但通常以设备无关单位指定的尺寸会为您完成这项工作。
  • 您实际上不需要(也不应该)在 Loaded 事件中执行此操作。只需覆盖表单的 MeasureOverride 并根据将要返回的所需大小设置最小值。效果相同,但是可以正确处理对子项的更改,否则会影响它,因为它在每个度量上运行,而不仅仅是初始度量。此外,使用 Math.Ceiling 钳制它们的值。在任何 DPI 设置上都像魅力一样工作。
【解决方案3】:

&lt;Window&gt; 部分中包含 MinHeight="MinSize" MinWidth="MinSize"

MinSize = 所需的整数值,例如 400/350 等。

<Window x:Class="IOTA_WPF.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" 
    WindowState="Maximized"
    MinHeight="400" MinWidth="650">

【讨论】:

  • MinSize 不是一个固定值,它取决于 DPI 设置、字体大小设置等,据我所知这不是一个有效的解决方案。无论如何感谢您的尝试。
  • MinSize 表示我在示例中解释的所需大小
  • 我知道了,但在 WPF 中,您在屏幕上看到的内容取决于各种设置,即使是固定大小,如 DPI、字体大小等。请查看此链接 msdn.microsoft.com/en-us/library/ms748828(v=vs.110).aspx
  • 这正是我在问题中要问的,伙计;)
【解决方案4】:

我想我记得在某处(我可能是错的)读到堆栈面板具有基于无穷大的边框,并且无法处理此类大小问题。

来自http://msdn.microsoft.com/en-us/library/ms754152.aspx

DockPanel 与 StackPanel

虽然 DockPanel 也可以“堆叠”子元素,但 DockPanel 和 StackPanel 在某些使用场景中不会产生类似的结果。例如,子元素的顺序会影响它们在 DockPanel 中的大小,但不会影响它们在 StackPanel 中的大小。这是因为StackPanel 在PositiveInfinity 的堆叠方向测量,而DockPanel 只测量可用大小。

帖子的一部分也谈到了嵌套面板。这可能是您需要的。

或者也许使用状态在底行的网格?

【讨论】:

    【解决方案5】:

    您可以将项目放入包含组成部分的行的网格中吗?

    所有必须具有最小高度的项目都可以以相似的最小高度排列。

    添加最小高度 = Window.MinHeight。因此,窗口永远不会小于必要行的总最小高度,因此应始终显示这些行。

    【讨论】:

      【解决方案6】:

      您可以设置控件的 MinHeight 属性以防止它变得比所需的小。

      【讨论】:

      • 我试过了,但它不起作用 :( 无论如何,我认为布局系统必须知道它正在裁剪用户控件,然后必须是一种无需在代码中设置固定值的方式,这会使维护更加困难。跨度>
      猜你喜欢
      • 2020-04-27
      • 1970-01-01
      • 2011-07-14
      • 2017-09-19
      • 2023-04-11
      • 1970-01-01
      • 1970-01-01
      • 2012-10-09
      • 2013-04-13
      相关资源
      最近更新 更多