Silverlight ChildWindow для WPF - PullRequest
       7

Silverlight ChildWindow для WPF

11 голосов
/ 09 февраля 2010

возможно ли сделать ChildWindow как ChildWindow в Silverlight, но для WPF? Я пытался адаптировать Silverlight ChildWindow для WPF, но столкнулся с проблемами с трансформациями и не смог установить родителя всплывающего окна. Я пытаюсь сделать что-то, что работает симулировано, поэтому мне не нужно добавлять код в XAML для всплывающих окон. Есть идеи?

Ответы [ 4 ]

9 голосов
/ 10 февраля 2010

Этот класс должен делать то, что вы хотите сделать:

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 в родительском окне (оно найдет окно, чтобы заблокировать его с помощью маски), и установите для содержимого все, что вы хотите, чтобы оно появлялось (и вызывайте метод Show, когда Вы хотите, чтобы это было показано, конечно). Вы должны придумать оболочку для всплывающих окон (то есть что-то с рамкой и кнопкой закрытия, которая вызывает метод close) самостоятельно, но это не должно быть сложно, и, очевидно, удалите кнопку-заполнитель в конструкторе. (он просто показывает, как это будет выглядеть).

Единственная проблема, связанная с этим, заключается в том, что он будет работать только с окнами, которые имеют свое содержимое (то есть то, что в Silverlight называется «LayoutRoot») - это сетка (по умолчанию при создании нового окна / страницы WPF / Silverlight). , Я настроил его на работу со всеми панелями, но выглядит странно, когда используется со StackPanel или DockPanel (как и ожидалось). Если это не сработает, дайте мне знать, и мы что-нибудь придумаем.

Если вы поиграете с ним, вы, вероятно, сможете заставить анимацию выглядеть ближе к исходному всплывающему окну (возможно, с помощью некоторого замедления). Также может быть лучший способ найти рут, я только что придумал этот метод на лету, но я думаю, что он будет работать (хотя, опять же, только с Contentcontrol с его содержимым, установленным в сетку).

Дайте мне знать, если у вас есть какие-либо вопросы / проблемы, и я надеюсь, что это решит вашу проблему.

2 голосов
/ 15 августа 2011

См. Элемент управления ChildWindow, доступный в Extended WPF Toolkit здесь. http://wpftoolkit.codeplex.com/wikipage?title=ChildWindow&referringTitle=Home

2 голосов
/ 24 марта 2010

Взгляните на BubbleBurst Sourcecode . GameOverView делает именно то, что вы ищете.

1 голос
/ 09 февраля 2010

Просто наследуйте от Window и вызывайте ShowDialog из родительского окна.

...