2016-02-26 65 views
1

我无法将弹出窗口的所有者设置为应用程序主窗口。WPF + PRISM如何将弹出窗口的所有者作为主窗口

在这里,我做了什么。

  1. 创建一个带有自定义PopupWindow的主窗口。

    <Window x:Class="MainWindow" 
        ... 
    
        <Window.Resources> 
         <Style x:Key="MessageWindowStyle" TargetType="{x:Type Window}"> 
          <Setter Property="Background" Value="Transparent" /> 
          <Setter Property="WindowStyle" Value="None" /> 
          <Setter Property="ResizeMode" Value="NoResize" /> 
          <Setter Property="BorderThickness" Value="1" /> 
          <Setter Property="SnapsToDevicePixels" Value="True" /> 
          <Setter Property="ShowInTaskbar" Value="False"/> 
          <Setter Property="AllowsTransparency" Value="True"/> 
         </Style> 
        </Window.Resources> 
    
        <i:Interaction.Triggers> 
         <interactionRequest:InteractionRequestTrigger SourceObject="{Binding MessageRequest, Mode=OneWay}"> 
          <interactionRequest:PopupWindowAction IsModal="True" CenterOverAssociatedObject="True" WindowStyle="{StaticResource MessageWindowStyle}" > 
           <interactionRequest:PopupWindowAction.WindowContent> 
            <controls:PageCustomPopup /> 
           </interactionRequest:PopupWindowAction.WindowContent> 
          </interactionRequest:PopupWindowAction> 
         </interactionRequest:InteractionRequestTrigger> 
        </i:Interaction.Triggers> 
    
        ... 
    </Window> 
    
  2. PageCustomPopup.xaml

这是弹出窗口基本XAML。

<UserControl x:Class="PageCustomPopup" 
     ... 
    </UserControl> 
  • PageCustomPopup.xaml.cs
  • 在该页面代码隐藏,我试图设置父,被装载在弹出窗口时。但它抛出异常。

    public partial class PageCustomPopup : UserControl, InteractionRequestAware, INotifyPropertyChanged 
        { 
         public PageCustomPopup() 
         { 
          Loaded += (sender, args) => 
          { 
           try 
           { 
            var parentWindow = this.Parent as Window; 
            if (parentWindow != null) 
            { 
             // This line fails with "Cannot set the Owner after the window is displayed." 
             //parentWindow.Owner = Application.Current.MainWindow; 
    
             // First, default to the main window's dimensions 
             parentWindow.Width = Application.Current.MainWindow.Width; 
             parentWindow.Height = Application.Current.MainWindow.Height; 
             parentWindow.Left = Application.Current.MainWindow.Left; 
             parentWindow.Top = Application.Current.MainWindow.Top; 
            } 
           } 
          } 
         } 
        } 
    
  • 主窗口后面的代码。

    public InteractionRequest<Notification> MessageRequest { get; private set; } 
    
    public MainWindow() 
    { 
        ... 
    
        MessageRequest = new InteractionRequest<Notification>(); 
    
        ... 
    } 
    
    void Button_OnClick(object sender, EventArgs e) 
    { 
        MessageRequest.Raise(new Notification(){ Title = "Title Text", Content = "Message to Display"}); 
    } 
    
  • 当显示自定义弹出窗口,它正确地显示在主窗口的中心。

    但问题是,当所有的窗口都被最小化时,如果点击任务栏上的应用程序图标,应用程序主窗口将显示出来并显示。无法选择任何东西。

    弹出式窗口被隐藏起来,不能放到前面。

    将Popup窗口放在前面的唯一方法是使用“Alt + Tab”键。

    我的问题是,如何将自定义弹出窗口的所有者设置为Application.Current.MainWindow? 这样,通过选择任务栏图标或Alt + Tab,显示主窗口和弹出窗口。

    回答

    1

    在,如果你不希望使用预览版的同时,你可以自己实现从PopupWindowAction得出:

    public class PopupChildWindowAction : PopupWindowAction 
    { 
        public static readonly DependencyProperty WindowOwnerProperty = DependencyProperty.Register(
         "WindowOwner", typeof (Window), typeof (PopupChildWindowAction), new PropertyMetadata(default(Window))); 
    
        public Window WindowOwner 
        { 
         get { return (Window) GetValue(WindowOwnerProperty); } 
         set { SetValue(WindowOwnerProperty, value); } 
        } 
    
        protected override Window GetWindow(INotification notification) 
        { 
         Window wrapperWindow; 
         if (this.WindowContent != null) 
         { 
          wrapperWindow = this.CreateWindow(); 
          if (wrapperWindow == null) 
           throw new NullReferenceException("CreateWindow cannot return null"); 
          wrapperWindow.Owner = WindowOwner; 
          wrapperWindow.DataContext = (object)notification; 
          wrapperWindow.Title = notification.Title; 
          this.PrepareContentForWindow(notification, wrapperWindow); 
         } 
         else 
          wrapperWindow = this.CreateDefaultWindow(notification); 
         if (this.WindowStyle != null) 
          wrapperWindow.Style = this.WindowStyle; 
         return wrapperWindow; 
        } 
    } 
    

    用法:

    <i:Interaction.Triggers> 
        <interactionRequest:InteractionRequestTrigger SourceObject="{Binding MessageRequest, Mode=OneWay}"> 
         <local:PopupChildWindowAction IsModal="True" CenterOverAssociatedObject="True" WindowStyle="{StaticResource MessageWindowStyle}" 
                 WindowOwner="{Binding ElementName=MyMainWindow}"> 
          <interactionRequest:PopupWindowAction.WindowContent> 
           <local:PageCustomPopup /> 
          </interactionRequest:PopupWindowAction.WindowContent> 
         </local:PopupChildWindowAction> 
        </interactionRequest:InteractionRequestTrigger> 
    </i:Interaction.Triggers> 
    
    +0

    谢谢Szabolcs !!!。此解决方案完美运作。 – ATati

    +0

    @ATati你可以请upvote并接受答案。 –

    1

    正如错误所述,您设置的属性太晚了。你在Loaded事件中设置它,所以窗口已经加载。您需要在显示窗口之前设置它。只是你知道,这已经在最新的Prism for WPF预览中得到了修复。

    如果你想升级你的NuGets使用最新的预览。以下是修复列表:

    https://github.com/PrismLibrary/Prism/wiki/Release-Notes--Jan-10,-2016#prism-for-wpf-611-pre2

    +0

    感谢布赖恩进行更新。我无法更新6.1.1的解决方案。但我尝试了Szabolcs的解决方案。这工作完美。 – ATati

    +0

    布赖恩,我使用6.2从Nuget但有类似的问题。当我查看实时属性窗口时,我的对话框中没有设置所有者。我可能会在这个问题上引发一个新的问题。 – Gusdor

    0

    刚刚更新@索博尔奇的回答:。实际上,我发现我的PRISM版本中没有一些功能。另外,微不足道的是,我的对话框样式并未保留,所以这段代码解决了我的问题。

    protected override Window GetWindow(INotification notification) 
         { 
          Window wrapperWindow; 
          if (this.WindowContent != null) 
          { 
           wrapperWindow = new Window(); 
           if (wrapperWindow == null) 
            throw new NullReferenceException("CreateWindow cannot return null"); 
           wrapperWindow.Owner = WindowOwner; 
           wrapperWindow.DataContext = (object)notification; 
           wrapperWindow.Title = notification.Title; 
           this.PrepareContentForWindow(notification, wrapperWindow); 
          } 
          else 
           wrapperWindow = this.CreateDefaultWindow(notification); 
          return wrapperWindow; 
         } 
    

    下面的一组线没有编制,因为(可能是由于不同版本的PRISM的asselblies的)。所以我用wrapperWindow = new Window()初始化,并在行为类中的Loaded事件上应用样式,如下所示。

    AssociatedObject.Loaded += (sender, e) => 
          { 
           // get the window 
           Window window = Window.GetWindow((UserControl)sender); 
           if (window != null) 
           { 
            window.WindowStyle = WindowStyle.None; 
            window.ResizeMode = ResizeMode.NoResize; 
            window.Background = Brushes.Transparent; 
            window.WindowStartupLocation = WindowStartupLocation.CenterOwner; 
           } 
          }; 
    

    我不得不也改变了XAML一部分,因为我的主要windnow元素名称不可用

    <presentBehaviors:PopupChildWindowAction IsModal="False" CenterOverAssociatedObject="True" WindowOwner="{Binding RelativeSource={RelativeSource AncestorType=Window}}"> 
    
    相关问题