2010-02-08 74 views
11

是否有可能在Silverlight中創建ChildWindow,如ChildWindow,但對於WPF?我嘗試將Silverlight ChildWindow調整爲WPF,但遇到轉換問題並且無法設置Popup的父項。我正在嘗試製作一些類似的工具,因此我不必將代碼添加到XAML中以獲取彈出窗口。有任何想法嗎?用於WPF的Silverlight ChildWindow

回答

9

該類應該做你想做的事:

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; 
    } 
} 

只需設置父屬性的父窗口的任何框架元素(它會發現窗口與面罩阻止它),和將內容設置爲想要彈出的任何內容(當然,當您想要顯示時調用Show方法)。你必須自己拿出彈出包裝器(即帶有邊框和關閉按鈕的東西),但它不應該很難,並且顯然在構造器中移除佔位符按鈕(它只是爲了向你展示它的外觀)。

這樣做的唯一問題是它只能在具有內容的窗口上工作(即在Silverlight中名爲「LayoutRoot」的東西)是一個網格(當您創建新的WPF/Silverlight窗口/頁面時)。我已經將它設置爲適用於所有面板,但在與StackPanel或DockPanel一起使用時(如預期的)它看起來很奇怪。如果這不適合你,讓我知道,我們會找出一些東西。

如果您使用它,您可能可以使動畫看起來更接近原始彈出(可能使用一些緩動)。也許還有更好的方法來找到根,我剛剛提出了這種方法,但我認爲它會起作用(儘管如此,只有將ContentControl的內容設置爲網格)。

如果您有任何疑問/問題,請告知我,我希望這可以解決您的問題。

+0

您不能在根之前動態注入Grid父節點並刪除它什麼時候完成? – 2015-02-05 14:06:03

+0

wow no xaml示例??? – user1034912 2017-07-28 00:03:38

1

只從窗口派生並從父窗口調用ShowDialog。

+0

這就是所有罰款和花花公子可用ChildWindow控制多數民衆贊成,但我不希望有一個新的窗口。我希望能夠在當前窗口中顯示一個面紗,並在當前窗口中顯示新的ChildWindow。我完全熟悉Windows如何工作,如何製作窗口和對話框,但這不是我的目標。我的目標就像我在上面的帖子中所說的,與Silverlight的ChildWindow相同,但是在WPF中。 – Jeff 2010-02-09 00:51:41

+0

奇怪的是,這是我一直在尋找的,但它還沒有upvoted,所以我沒有讀它。我最終意識到WPF的Window類是WPF中模態對話所需要的。誠然,它不完全像Silverlight的ChildWindow。但是它是模態的,只要你調用ShowDialog。所有使用ChildWindow端口的Silverlight代碼都很容易,如果我只是將構造函數更改爲Window,並將Show顯示爲ShowDialog。 – 2013-08-27 18:52:02

+0

我認爲Silverlight的ChildWindow顯示不會阻止當前的線程,而WPF的ShowDialog會阻止它,所以您必須小心您的代碼的邏輯不會中斷 – 2015-02-05 14:09:01

2
+0

他們已經改變了ChildWindows和MessageBox類 - 「從2.0版開始,MessageBox(和ChildWindow)從WindowControl派生出來,不再管理父級的背景或者根據其父​​級的大小來定位自己。WindowContainer現在應該用來包含這些控件。「 – 2015-02-05 14:17:40

+0

順便說一句,他們說舊版本將保持可用,但不知道它在最新版本的存儲庫中的位置 – 2015-02-05 14:18:49

相關問題