Silverlight ChildWindow для WPF

действительно ли возможно сделать ChildWindow как ChildWindow в Silverlight, но для WPF? Я попытался адаптировать Silverlight ChildWindow к WPF, но столкнулся с проблемами с Преобразованиями и не бывший способный устанавливать Родителя Всплывающего окна. Я пытаюсь сделать что-то, что работает средство моделирования, таким образом, я не должен добавлять код к XAML для всплывающих окон. Какие-либо идеи?

11
задан Dave Clemmer 18 September 2011 в 18:37
поделиться

3 ответа

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

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

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

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

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

9
ответ дан 3 December 2019 в 08:29
поделиться

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

1
ответ дан 3 December 2019 в 08:29
поделиться

Взгляните на Исходный код BubbleBurst . GameOverView делает именно то, что вы ищете.

2
ответ дан 3 December 2019 в 08:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: