【问题标题】:Silverlight ChildWindow for WPF适用于 WPF 的 Silverlight ChildWindow
【发布时间】:2010-02-08 23:23:29
【问题描述】:

是否可以在 Silverlight 中创建一个类似于 ChildWindow 的 ChildWindow,但对于 WPF?我试图使 Silverlight ChildWindow 适应 WPF,但遇到了转换问题并且无法设置弹出窗口的父级。我正在尝试制作一些可以模拟的东西,所以我不必为弹出窗口添加代码到 XAML。有什么想法吗?

【问题讨论】:

    标签: wpf silverlight childwindow


    【解决方案1】:

    这个类应该做你想做的事:

    public class SilverlightishPopup
    {
        private Rectangle maskRectangle = new Rectangle { Fill = new SolidColorBrush(Colors.DarkGray), Opacity = 0.0 };
    
        public FrameworkElement Parent
        {
            get;
            set;
        }
    
        public FrameworkElement Content
        {
            get;
            set;
        }
    
        public SilverlightishPopup()
        {
            Button button = new Button();
            button.Width = 100;
            button.Height = 200;
            button.Content = "I am the popup!";
    
            button.Click += delegate { Close(); };
    
            Content = button;
        }
    
        public void Show()
        {
            Grid grid = GetRootGrid();
    
            if (grid != null)
            {
                DoubleAnimation opacityAnimation = new DoubleAnimation(0.5, new Duration(TimeSpan.FromSeconds(0.5)));
    
                Storyboard opacityBoard = new Storyboard();
                opacityBoard.Children.Add(opacityAnimation);
    
                Storyboard.SetTarget(opacityAnimation, maskRectangle);
                Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath("(Opacity)"));
    
                opacityBoard.Completed += delegate
                {
                    ScaleTransform scaleTransform = new ScaleTransform(0.0, 0.0, Content.Width / 2.0, Content.Height / 2.0);
                    Content.RenderTransform = scaleTransform;
    
                    grid.Children.Add(Content);
    
                    Storyboard scaleBoard = new Storyboard();
    
                    DoubleAnimation scaleXAnimation = new DoubleAnimation(1.0, TimeSpan.FromSeconds(0.5));
    
                    scaleBoard.Children.Add(scaleXAnimation);
    
                    Storyboard.SetTarget(scaleXAnimation, Content);
                    Storyboard.SetTargetProperty(scaleXAnimation, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleX)"));
    
                    DoubleAnimation scaleYAnimation = new DoubleAnimation(1.0, TimeSpan.FromSeconds(0.5));
    
                    scaleBoard.Children.Add(scaleYAnimation);
    
                    Storyboard.SetTarget(scaleYAnimation, Content);
                    Storyboard.SetTargetProperty(scaleYAnimation, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleY)"));
    
                    scaleBoard.Begin();
                };
    
                opacityBoard.Begin();
    
                grid.Children.Add(maskRectangle);
            }
        }
    
        public void Close()
        {
            Grid grid = GetRootGrid();
    
            if (grid != null)
            {
                ScaleTransform scaleTransform = new ScaleTransform(1.0, 1.0, Content.Width / 2.0, Content.Height / 2.0);
                Content.RenderTransform = scaleTransform;
    
                Storyboard scaleBoard = new Storyboard();
    
                DoubleAnimation scaleXAnimation = new DoubleAnimation(0.0, TimeSpan.FromSeconds(0.5));
    
                scaleBoard.Children.Add(scaleXAnimation);
    
                Storyboard.SetTarget(scaleXAnimation, Content);
                Storyboard.SetTargetProperty(scaleXAnimation, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleX)"));
    
                DoubleAnimation scaleYAnimation = new DoubleAnimation(0.0, TimeSpan.FromSeconds(0.5));
    
                scaleBoard.Children.Add(scaleYAnimation);
    
                Storyboard.SetTarget(scaleYAnimation, Content);
                Storyboard.SetTargetProperty(scaleYAnimation, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleY)"));
    
                scaleBoard.Completed += delegate
                {
                    DoubleAnimation opacityAnimation = new DoubleAnimation(0.5, 0.0, new Duration(TimeSpan.FromSeconds(0.5)));
    
                    Storyboard opacityBoard = new Storyboard();
                    opacityBoard.Children.Add(opacityAnimation);
    
                    Storyboard.SetTarget(opacityAnimation, maskRectangle);
                    Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath("(Opacity)"));
    
                    opacityBoard.Completed += delegate
                    {
                        grid.Children.Remove(maskRectangle);
                        grid.Children.Remove(Content);
                    };
    
                    opacityBoard.Begin();
                };
    
                scaleBoard.Begin();
            }
        }
    
        private Grid GetRootGrid()
        {
            FrameworkElement root = Parent;
    
            while (root is FrameworkElement && root.Parent != null)
            {
                FrameworkElement rootElement = root as FrameworkElement;
    
                if (rootElement.Parent is FrameworkElement)
                {
                    root = rootElement.Parent as FrameworkElement;
                }
            }
    
            ContentControl contentControl = root as ContentControl;
    
            return contentControl.Content as Grid;
        }
    }
    

    只需将 Parent 属性设置为父窗口中的任何 Framework 元素(它会找到 Window 以使用掩码阻止它),并将内容设置为您想要弹出的任何内容(并调用 Show 方法当然,您希望它显示出来)。您必须自己提出弹出包装器(即带有边框和调用 close 方法的关闭按钮的东西),但这应该不难,并且显然删除了构造函数中的占位符按钮(它只是为了向您展示它的外观)。

    唯一的问题是它只适用于具有其内容的窗口(即 Silverlight 中名为“LayoutRoot”的东西)是网格(创建新 WPF/Silverlight 窗口/页面时的默认设置) .我将它设置为适用于所有面板,但与 StackPanel 或 DockPanel 一起使用时看起来很奇怪(如预期的那样)。如果这对您不起作用,请告诉我,我们会想办法解决的。

    如果您使用它,您可能可以让动画看起来更接近原始弹出窗口(可能使用一些缓动)。也可能有更好的方法来找到根,我只是临时想出了那个方法,但我认为它会起作用(尽管同样,只有 Contentcontrol 的内容设置为网格)。

    如果您有任何疑问/问题,请告诉我,希望这能解决您的问题。

    【讨论】:

    • 你不能在根之前动态注入一个 Grid 父级并在完成后将其删除吗?
    【解决方案2】:

    看看BubbleBurst Sourcecode。 GameOverView 完全符合您的要求。

    【讨论】:

      【解决方案3】:

      只需从 Window 派生并从父窗口调用 ShowDialog。

      【讨论】:

      • 这一切都很好,但我不想要一个新窗口。我希望能够在当前窗口上显示面纱,并在当前窗口中显示新的 ChildWindow。我完全熟悉 windows 的工作原理以及如何制作 windows 和对话框,但这不是我的目标。我的目标正如我在上面的帖子中所说的,与 silverlight 的 ChildWindow 的感觉相同,但在 WPF 中。
      • 奇怪的是,这正是我想要的,但它还没有被投票,所以我没有阅读它。我最终意识到 WPF 的 Window 类是我在 WPF 中的模态对话框所需要的。确实,它与 Silverlight 的 ChildWindow 不完全一样。但它是模态的,只要你调用ShowDialog。如果我只是将构造函数更改为 Window,并将 Show 更改为 ShowDialog,那么我所有使用 ChildWindow 端口的 Silverlight 代码都很容易。
      • 我认为 Silverlight 的 ChildWindow 的 Show 不会阻​​塞当前线程,而 WPF 的 ShowDialog 会阻塞它,所以你必须小心你的代码逻辑不会中断
      【解决方案4】:

      在此处查看扩展 WPF 工具包中可用的 ChildWindow 控件 http://wpftoolkit.codeplex.com/wikipage?title=ChildWindow&referringTitle=Home

      【讨论】:

      • 他们已经更改了 ChildWindows 和 MessageBox 类 - “从 2.0 版开始,MessageBox(和 ChildWindow)是从 WindowControl 派生的,不再管理其父级的背景或基于其父级的定位大小。现在应该使用 WindowContainer 来包含这些控件。"
      • 顺便说一句,他们说旧版本仍然可用,但不确定它在最新版本的存储库中的位置
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多