2010-02-08 11 views
11

là có thể tạo ChildWindow như ChildWindow trong Silverlight, nhưng đối với WPF? Tôi đã cố gắng để thích ứng với Silverlight ChildWindow để WPF nhưng chạy vào các vấn đề với Transformations và không thể thiết lập cha mẹ của Popup. Tôi đang cố gắng để làm một cái gì đó mà làm việc simular vì vậy tôi không phải thêm mã vào XAML cho quảng cáo. Bất kỳ ý tưởng?Silverlight ChildWindow dành cho WPF

Trả lời

9

Lớp này nên làm những gì bạn muốn làm:

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

Chỉ cần thiết lập thuộc tính cha để bất kỳ yếu tố khung trong cửa sổ cha mẹ (nó sẽ tìm thấy cửa sổ để ngăn chặn nó với mặt nạ), và thiết lập nội dung cho bất cứ điều gì bạn muốn được xuất hiện (và gọi phương thức Show khi bạn muốn nó được hiển thị, tất nhiên). Bạn sẽ phải đưa ra trình bao bọc pop-up (tức là một cái gì đó có viền và nút đóng gọi phương thức đóng), nhưng không khó, và rõ ràng là xóa nút giữ chỗ trong hàm tạo (nó chỉ ở đó để cho bạn thấy nó trông như thế nào).

Vấn đề duy nhất với điều này là nó chỉ hoạt động trên các cửa sổ có nội dung của chúng (tức là thứ được đặt tên là "LayoutRoot" trong Silverlight) là một lưới (mặc định khi bạn tạo một WPF/Silverlight Window/Trang mới)). Tôi đã có nó thiết lập để làm việc cho tất cả các bảng, nhưng có vẻ lạ khi được sử dụng với một StackPanel hoặc một DockPanel (như mong đợi). Nếu điều đó không hiệu quả với bạn, hãy cho tôi biết và chúng tôi sẽ tìm ra điều gì đó.

Nếu bạn chơi với nó, bạn có thể có được hình động gần giống với cửa sổ bật lên ban đầu hơn (có thể sử dụng một số nới lỏng). Cũng có thể có cách tốt hơn để tìm gốc, tôi chỉ nghĩ ra phương pháp đó khi đang bay, nhưng tôi nghĩ nó sẽ hoạt động (mặc dù một lần nữa, chỉ với một Contentcontrol có nội dung được đặt thành lưới).

Hãy cho tôi biết nếu bạn có bất kỳ câu hỏi/vấn đề nào và tôi hy vọng điều này sẽ giải quyết được vấn đề của bạn.

+0

bạn không thể tiêm cha mẹ lưới trước gốc và động nó khi hoàn thành? –

+0

wow no xaml example ??? – user1034912

1

Chỉ xuất phát từ Cửa sổ và gọi ShowDialog từ cửa sổ chính.

+0

Thats tất cả tiền phạt và dandy nhưng tôi không muốn có một cửa sổ mới. Tôi muốn có thể hiển thị một tấm màn che trên cửa sổ hiện tại, và có ChildWindow mới hiển thị bên trong hiện tại. Tôi hoàn toàn thất vọng với cách cửa sổ hoạt động và cách tạo cửa sổ và hộp thoại, nhưng đó không phải là mục tiêu của tôi ở đây. Mục tiêu của tôi là như tôi đã nói trong bài viết trên, cũng giống như ChildWindow của Silverlight nhưng trong WPF. – Jeff

+0

Thật kỳ lạ, đây là những gì tôi đang tìm kiếm, nhưng nó vẫn chưa được bình chọn nên tôi không đọc nó. Cuối cùng tôi nhận ra rằng lớp Window của WPF là những gì tôi cần cho một hộp thoại modal trong WPF. Đúng, nó không chính xác như ChildWindow của Silverlight. Nhưng nó là phương thức, miễn là bạn gọi ShowDialog. Tất cả mã Silverlight của tôi sử dụng các cổng ChildWindow dễ dàng hơn, nếu tôi chỉ thay đổi hàm tạo thành Window và Show thành ShowDialog. –

+0

Tôi nghĩ rằng Show của Silverlight ChildWindow không chặn thread hiện tại, trong khi ShowDialog của WPF chặn nó, vì vậy bạn phải cẩn thận mã logic của bạn không phá vỡ –

2

Xem thats kiểm soát ChildWindow sẵn trong Extended WPF Toolkit đây http://wpftoolkit.codeplex.com/wikipage?title=ChildWindow&referringTitle=Home

+0

họ đã thay đổi các lớp ChildWindows và MessageBox ở đó - "Bắt đầu với phiên bản 2.0, MessageBox (và ChildWindow) có nguồn gốc từ WindowControl và không còn quản lý nền của cha mẹ hoặc vị trí của chính nó dựa trên kích thước của cha mẹ. được sử dụng để chứa các điều khiển này." –

+0

btw, họ nói rằng phiên bản cũ hơn sẽ vẫn có sẵn, nhưng không chắc chắn nó ở đâu trong phiên bản mới nhất của kho lưu trữ –