Можно ли сделать ChildWindow как ChildWindow в Silverlight, но для WPF? Я попытался адаптировать Silverlight ChildWindow к WPF, но столкнулся с проблемами с Transformations и не смог установить Popup Parent. Я пытаюсь сделать что-то, что работает на симуляторе, поэтому мне не нужно добавлять код в XAML для всплывающих окон. Любые идеи?
Silverlight ChildWindow для WPF
Ответ 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 в родительском окне (он найдет окно, чтобы заблокировать его с помощью маски), и настройте содержимое на все, что вы хотите вывести (и вызовите метод Show, когда вы хотите, чтобы это было показано, конечно). Вам придется придумать всплывающую оболочку (то есть что-то с рамкой и кнопкой закрытия, которая вызывает метод close) самостоятельно, но это не должно быть сложно и, очевидно, удалить кнопку-заполнителя в конструкторе (он просто показывает вам, как он будет выглядеть).
Единственная проблема с этим заключается в том, что он будет работать только с окнами, которые имеют свой контент (то есть то, что называется "LayoutRoot" в Silverlight) является сеткой (по умолчанию при создании нового WPF/Silverlight Window/Page), Я решил, что он работает для всех панелей, но выглядит странно при использовании с StackPanel или DockPanel (как и ожидалось). Если это не сработает для вас, дайте мне знать, и мы что-нибудь придумаем.
Если вы играете с ним, вы, вероятно, можете заставить анимацию приблизиться к оригинальному всплывающему окну (возможно, используя некоторое ослабление). Также может быть лучший способ найти корень, я просто придумал этот метод "на лету", но я думаю, что он будет работать (хотя опять же, только с Contentcontrol с его содержимым, установленным в сетку).
Сообщите мне, есть ли у вас какие-либо вопросы/проблемы, и я надеюсь, что это решит вашу проблему.
Ответ 2
Посмотрите BubbleBurst Sourcecode. GameOverView выполняет именно то, что вы ищете.
Ответ 3
См. элемент управления ChildWindow, доступный в расширенном наборе инструментов WPF. http://wpftoolkit.codeplex.com/wikipage?title=ChildWindow&referringTitle=Home
Ответ 4
Просто выведите из окна и вызовите ShowDialog из родительского окна.