Search code examples
c#wpfxamlprism-6

WPF - PRISM: How to close CustomPopupWindow with button click


This one is playing with me, and I cannot seem to figure it out - I need some external help here bro's!

I want a popup window that does not have the title, minimize, maximize, and close buttons, because we want to style it ourselves and add a custom close button on the popup's screen.

So I followed these links to get where I am now:

https://msdn.microsoft.com/en-us/library/ff921081(v=pandp.40).aspx https://msdn.microsoft.com/en-us/library/gg405494(v=pandp.40).aspx https://www.codeproject.com/Articles/269364/MVVM-PRISM-Modal-Windows-by-using-Interaction-Requ

But I still can't figure out how to achieve this. The basic windows have "OK" and "Cancel" buttons, but those are defaults, and I do not want that, that is why I went the "Custom View" way.

Here is my Main Window's xaml:

<Window x:Class="Prototype.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:views="clr-namespace:Prototype.Views"
        Height="349.146" Width="727.317"
        WindowState="Maximized">
    <Grid>
        <Button Command="{Binding RaiseCustomPopupViewCommand}">Show Popup Window</Button>

        <i:Interaction.Triggers>
            <prism:InteractionRequestTrigger SourceObject="{Binding CustomPopupViewRequest, Mode=OneWay}">
                <prism:PopupWindowAction IsModal="True" CenterOverAssociatedObject="True">
                    <prism:PopupWindowAction.WindowStyle>
                        <Style TargetType="Window">
                            <Setter Property="ShowInTaskbar" Value="False"/>
                            <Setter Property="WindowStyle" Value="None"/>
                            <Setter Property="ResizeMode" Value="NoResize"/>
                        </Style>
                    </prism:PopupWindowAction.WindowStyle>
                    <prism:PopupWindowAction.WindowContent>
                        <views:CustomPopupView  />
                    </prism:PopupWindowAction.WindowContent>
                </prism:PopupWindowAction>
            </prism:InteractionRequestTrigger>
        </i:Interaction.Triggers>
    </Grid>
</Window>

And here it the Main Window's code:

public class MainWindowViewModel : BindableBase
{
    public InteractionRequest<INotification> CustomPopupViewRequest { get; private set; }

    public MainWindowViewModel()
    {
        CustomPopupViewRequest = new InteractionRequest<INotification>();
    }

    public DelegateCommand RaiseCustomPopupViewCommand => new DelegateCommand(RaiseCustomPopupView, CanRaiseCustomPopupView);

    public string InteractionResultMessage { get; private set; }

    private void RaiseCustomPopupView()
    {
        InteractionResultMessage = "";
        CustomPopupViewRequest.Raise(new Notification { Content = "Message for the CustomPopupView", Title = "Custom Popup" });
    }

    private bool CanRaiseCustomPopupView()
    {
        return true;
    }
}

The InteractionRequestTrigger's SourceObject is a UserControl.

Here is it's xaml:

<UserControl x:Class="Prototype.Views.CustomPopupView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:prism="http://prismlibrary.com/"
             prism:ViewModelLocator.AutoWireViewModel="True"
             xmlns:local="clr-namespace:Prototype.Views"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             MinWidth="300" MinHeight="100">
    <StackPanel Orientation="Vertical" Background="Gray">
        <Button DockPanel.Dock="Right"
                Content="Close"/>
    </StackPanel>
</UserControl>

So as you can see, I have a "Close" button in the UserControl.

I tried using a Command, but even then I cannot acccess the window or execute something to close the window.

Is there some kind of prism command or something I am not aware of?

Is it possible to close the window the way I want with a button?

Any help will be greatly appreciated! :)


Solution

  • No matter, I just managed to solve this on my own :).

    I was thinking of it differently, but what I actually wanted was the CancelCommand.

    This is how we implement it in the UserControl, with NO other changes. Everything is still the same as described above, but the CustomPopup now have the following in it's ViewModel:

    public class CustomPopupViewModel : BindableBase, IInteractionRequestAware
    {
        public CustomPopupViewModel()
        {
            CancelCommand = new DelegateCommand(CancelInteraction);
        }
    
        private CustomPopupSelectionNotification notification;
    
        public INotification Notification
        {
            get
            {
                return this.notification;
            }
            set
            {
                if (value is CustomPopupSelectionNotification)
                {
                    this.notification = value as CustomPopupSelectionNotification;
                    this.OnPropertyChanged(() => this.Notification);
                }
            }
        }
    
        public Action FinishInteraction { get; set; }
    
        public System.Windows.Input.ICommand CancelCommand { get; private set; }
    
        public void CancelInteraction()
        {
            if (notification != null)
            {
                notification.SelectedItem = null;
                notification.Confirmed = false;
            }
    
            FinishInteraction();
        }
    }
    

    You will also notice that we have a class called CustomPopupSelectionNotification.

    Here is it's code:

    public class CustomPopupSelectionNotification : Confirmation
    {
        public CustomPopupSelectionNotification()
        {
            Items = new List<string>();
            SelectedItem = null;
        }
    
        public CustomPopupSelectionNotification(IEnumerable<string> items) : this()
        {
            foreach (string item in items)
            {
                Items.Add(item);
            }
        }
    
        public IList<string> Items { get; private set; }
    
        public string SelectedItem { get; set; }
    }   
    

    So in short, I am just cancelling the popup, instead of trying to close it.

    I then added the command CancelCommand to the "Close" button on my UserControl.