是否有可能在Silverlight中制作像ChildWindow一样的ChildWindow,但对于WPF?我尝试将Silverlight ChildWindow改编为WPF,但遇到了转换问题而无法设置Popup的Parent。我正在尝试制作一些有效的东西,所以我不必为弹出窗口添加代码到XAML。有任何想法吗?
是否有可能在Silverlight中制作像ChildWindow一样的ChildWindow,但对于WPF?我尝试将Silverlight ChildWindow改编为WPF,但遇到了转换问题而无法设置Popup的Parent。我正在尝试制作一些有效的东西,所以我不必为弹出窗口添加代码到XAML。有任何想法吗?
这个课应该做你想做的事:
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的内容设置为网格)。
如果您有任何疑问/问题,请告诉我,我希望这能解决您的问题。
这个课应该做你想做的事:
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的内容设置为网格)。
如果您有任何疑问/问题,请告诉我,我希望这能解决您的问题。
请参阅此处的Extended WPF Toolkit中提供的ChildWindow控件 http://wpftoolkit.codeplex.com/wikipage?title=ChildWindow&referringTitle=Home
看看吧 BubbleBurst源代码。 GameOverView完全符合您的要求。
只需从Window派生并从父窗口调用ShowDialog。