首页 > 解决方案 > 通过在代码中设置高度和宽度来缩小视图大小不会正确更新

问题描述

在我的应用程序中,我们有一个包含许多嵌套视图的视图,以提供一些常见的功能,即:

在这种情况下:

一个带有 * 大小的主内容网格单元格和一个固定宽度的单元格的 ErrorPanelView (UserControl),其中包含一个验证消息面板(如果任何验证失败) - 此面板具有固定宽度,并且根据需要可见或折叠。

主要内容再次包含一个 ButtonPanelView,其中包含一个 * 大小的内容网格单元格和一个固定高度的单元格,其中包含标准按钮(确定、取消等)

主要内容然后保存“实际”视图 - 这可能有一个 min/maxHeight 和 min/maxWidth,对于这个例子,min/max 值是相同的,所以大小是静态的。

当视图出现验证错误时,validationPanel 变为可见。整体视图将按预期调整大小(宽度扩展),到目前为止一切都很好。但是,当用户处理验证错误时,验证面板应该消失,并且窗口应该缩小到其原始大小。确实发生的是内部视图将正确调整大小(至少看起来如此),但外部视图(ErrorPanelView 用户控件)将保持其更大的尺寸,并在验证面板之前可见的地方留下一个黑色区域。

用户单击用户控件的那一刻,用户控件将捕捉到其预期的(原始)大小。

在此处输入图像描述

我无法弄清楚我在这里缺少什么。

据我所知,尺寸计算正确,用户控件的高度和宽度设置为正确的值,但是序列有问题吗?- 或者我应该明确地调用一些系统事件?

还是完全不同的东西?

我难住了。

private static void CalculateWindowSize(BaseWindow window, List<View> views, bool adjustCurrentSize)
        {
            // Calculate the extra space the window consumes.
            View topView = views.First();
            double heightDiff = window.ActualHeight - topView.ActualHeight;

            double widthDiff = window.ActualWidth - topView.ActualWidth;
            double ww = window.Width; //
            double tvw = topView.Width;


            const double zeroTolerance = 0.6;
            double maxHeightMax = 0, maxWidthMax = 0;
            double maxHeightSum = 0, maxWidthSum = 0;
            double minHeightMax = 0, minWidthMax = 0;
            double minHeightSum = 0, minWidthSum = 0;
            double heightSum = 0, widthSum = 0;
            double heightMax = 0, widthMax = 0;
            foreach (View view in views)
            {
                ViewSizeBehaviour viewHeightBehaviour = GetHeightSizeBehaviour(view);
                ViewSizeBehaviour viewWidthBehaviour = GetWidthSizeBehaviour(view);

                switch (viewHeightBehaviour)
                {
                    case ViewSizeBehaviour.Sum:
                    {
                        if (!double.IsInfinity(view.MaxHeight)) maxHeightSum += view.MaxHeight;
                        if (Math.Abs(view.MinHeight) > zeroTolerance) minHeightSum += view.MinHeight;

                        // Default to MinHeight if WindowHeight not defined
                        if (!double.IsNaN(view.WindowHeight)) heightSum += view.WindowHeight;
                        else heightSum += view.MinHeight;
                        break;
                    }
                    case ViewSizeBehaviour.Max:
                    {
                        if (!double.IsInfinity(view.MaxHeight)) maxHeightMax = Math.Max(maxHeightMax, view.MaxHeight);
                        if (Math.Abs(view.MinHeight) > zeroTolerance) minHeightMax = Math.Max(minHeightMax, view.MinHeight);

                        // Default to MinHeight if WindowHeight not defined
                        heightMax = Math.Max(heightMax, !double.IsNaN(view.WindowHeight) ? view.WindowHeight : view.MinHeight);
                        break;
                    }
                }

                switch (viewWidthBehaviour)
                {
                    case ViewSizeBehaviour.Sum:
                    {
                        if (!double.IsInfinity(view.MaxWidth)) maxWidthSum += view.MaxWidth;
                        if (Math.Abs(view.MinWidth) > zeroTolerance) minWidthSum += view.MinWidth;

                        // Default to MinWidth if WindowWidth not defined
                        if (!double.IsNaN(view.WindowWidth)) widthSum += view.WindowWidth;
                        else widthSum += view.MinWidth;
                        break;
                    }
                    case ViewSizeBehaviour.Max:
                    {
                        if (!double.IsInfinity(view.MaxWidth)) maxWidthMax = Math.Max(maxWidthMax, view.MaxHeight);
                        if (Math.Abs(view.MinWidth) > zeroTolerance) minWidthMax = Math.Max(minWidthMax, view.MinWidth);

                        // Default to MinWidth if WindowWidth not defined
                        widthMax = Math.Max(widthMax, !double.IsNaN(view.WindowWidth) ? view.WindowWidth : view.MinWidth);
                        break;
                    }
                }
            }

            if (adjustCurrentSize)
            {
                window.Height = Math.Max(heightSum, heightMax) + heightDiff;
                window.Width = Math.Max(widthSum, widthMax) + widthDiff;
            }

            // Only set maximum height & width if they are greater than zero. Otherwise all views have specified Infinity as max height

            double maxHeight = Math.Max(maxHeightSum, maxHeightMax);
            double maxWidth = Math.Max(maxWidthSum, maxWidthMax);
            if (Math.Abs(maxHeight) > zeroTolerance)
            {
                window.MaxHeight = maxHeight + heightDiff;
                if (window.MaxHeight < window.Height || window.MaxHeight < window.ActualHeight)
                {
                    window.Height = window.MaxHeight;
                }
            }
            if (Math.Abs(maxWidth) > zeroTolerance)
            {
                window.MaxWidth = maxWidth + widthDiff;
                if (window.MaxWidth < window.Width || window.MaxWidth < window.ActualWidth)
                {
                    window.Width = window.MaxWidth;
                }
            }

            // Minimum height & width are the maximum of either the sum or max calculations

            window.MinHeight = Math.Max(minHeightSum, minHeightMax) + heightDiff;
            window.MinWidth = Math.Max(minWidthSum, minWidthMax) + widthDiff;

标签: c#wpfxamlevent-handling

解决方案


问题上的标签说WPFand XAML,但代码是这样写的,这是一个 winforms 应用程序,所以我不是 100% 确定如何回答这个问题。
我将假设标签是正确的并且您是 WPF 的新手。

基本上,您问题中的所有代码在 WPF 应用程序中都不需要。WPF 相对于 Winforms 的主要优势之一是内容的自动调整大小;Winforms 没有为您做的事情。

在 WPF 中,您在 UserControl 中设置 XAML,以便当您遇到错误情况时,验证错误 UserControl 变为 Visibile。您只需将布尔属性绑定到VisibilityUserControl 的属性(也使用 ValueConverter),然后在处理错误时,布尔值设置为 false 并且验证 UserControl 消失,WPF 会自动调整其余内容的大小。您无需编写任何代码来调整大小(这是旧的 Winforms 方式)。

当然,在 XAML 中需要学习很多东西来设置您的 UserControl,以便自动调整大小以您希望的方式发生,但是不再需要编写包含所有数学和计算和重绘的繁琐代码。

希望这能让你指出正确的方向。有大量的教程和帮助可以在 XAML 中设置 UserControls 并将布尔属性绑定到控件上的 Visibility 属性以及使用 IValueConverters。


推荐阅读