【问题标题】:Using Adorner to show stretched overlay containing UIElements使用 Adorner 显示包含 UIElements 的拉伸覆盖
【发布时间】:2014-07-02 15:45:28
【问题描述】:

我使用Adorner 在单击按钮时创建叠加层。此覆盖包含一个表单,例如基于其他UIElements(ButtonTextBox 等)的登录表单。 基本上是这样完成的:Click

但是有一个问题。覆盖应填满可用空间。所以我将表单面板的Vertical-/HorizontalAlignment 属性(这是ControlAdorner 的子级)设置为Stretch。但是,它只占用显示面板所需的空间,而不是使用整个可用空间。

我认为这就是原因:
ControlAdorner 的方法MeasureOverride 以正确的大小(可用空间)调用。但是随后 Child 的Measure-方法用于计算所需的大小。而且该调用似乎忽略了Stretch 属性。可能是因为 Child 没有设置Parent,因为 Child 是动态生成的。

有没有办法让Adorner 的孩子正常工作?

【问题讨论】:

  • 我是否理解正确,从用户的角度来看,当单击按钮时 GUI 应该切换到另一个面板?
  • 简单地说,是的。 :) 按钮被点击,表单面板弹出在所有其他UIElements 之上。面板本身具有半透明背景色并包含表单。但我忘了提到按钮包括。 Overlay-Panel 将被封装在一个单独的 UserControl 中(用于可重用性)。所以结果是一种手势友好的(对于 Kinect)ComboBox:程序员只需要添加这个 ComboBox 并设置装饰元素(例如 KinectRegion 的子元素)并获得一个手势友好的 ComboBox,它将在顶部显示 ComboBoxItems装饰元素(拉伸)。
  • 所以你选择装饰器的原因是你想在你的登录表单周围/下面看到原始 UI 的阴影......我明白了......
  • 您在使用主窗口的 AdornerLayer 吗?请在添加装饰器的位置显示您的代码...
  • 我现在(但明天)无法访问代码。但是 xaml 看起来像这样:窗口包含一个 KinectRegion,其中包含一个 AdornerDecorator(因此覆盖层将位于 KinectRegion 下方!),其中包含一个 KinectScrollViewer,其中包含一个 Panel,其中包含提到的按钮/组合框-用户控件。然后将KinectScrollViewer 传递给ControlAdorner 的构造函数,因此KinectScrollViewer 是装饰元素。

标签: c# wpf adorner


【解决方案1】:

我搞定了 :-)

由于Adorners MeasureOverride 已经计算了覆盖装饰元素的正确尺寸,我们不需要覆盖它。但是我们需要覆盖ArrangeOverride,因为我们需要调用子级的Arrange 方法。否则可能不会显示。

所以这是一个有效的示例代码:

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace AdornerTest {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
        }

        private void button_Click(object sender, RoutedEventArgs e) {
            StackPanel overlayPanel = new StackPanel() {
                Background = new SolidColorBrush(Color.FromArgb(0x99, 0, 0, 0xFF)),
            };

            // example content 1
            Rectangle overlayChild1 = new Rectangle() {
                Fill = new SolidColorBrush(Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF)),
                Margin = new Thickness(10),
                Height = 50,
            };
            overlayPanel.Children.Add(overlayChild1);

            // example content 2
            Button overlayChild2 = new Button();
            overlayChild2.Content = "asdasd";
            overlayChild2.Margin = new Thickness(10);
            overlayPanel.Children.Add(overlayChild2);

            OverlayAdorner adorner = new OverlayAdorner(mainGrid) {
                Content = overlayPanel,
            };
            AdornerLayer.GetAdornerLayer(mainGrid).Add(adorner);
        }
    }


    class OverlayAdorner : Adorner {
        private FrameworkElement _content;

        public OverlayAdorner(UIElement adornedElement)
            : base(adornedElement) {
        }

        protected override int VisualChildrenCount {
            get {
                return _content == null ? 0 : 1;
            }
        }

        protected override Visual GetVisualChild(int index) {
            if (index != 0) throw new ArgumentOutOfRangeException();
            return _content;
        }

        public FrameworkElement Content {
            get { return _content; }
            set {
                if (_content != null) {
                    RemoveVisualChild(_content);
                }
                _content = value;
                if (_content != null) {
                    AddVisualChild(_content);
                }
            }
        }

        protected override Size ArrangeOverride(Size finalSize) {
            _content.Arrange(new Rect(new Point(0, 0), finalSize));
            return base.ArrangeOverride(finalSize);
        }
    }
}

MainWindow.xaml

<Window x:Class="AdornerTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <AdornerDecorator>
        <Grid Name="mainGrid">
            <Button Content="Show Overlay" Name="button" VerticalAlignment="Top" Click="button_Click" />
        </Grid>
    </AdornerDecorator>
</Window>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-18
    • 1970-01-01
    • 2011-11-20
    • 1970-01-01
    • 1970-01-01
    • 2017-12-24
    • 2018-11-14
    • 2010-11-22
    相关资源
    最近更新 更多