Click here to Skip to main content
15,888,113 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Am currently porting a GUI from Unix X11 XWindows to WPF/MVVM. This GUI has a main window, from which many other sub-windows can be opened. These sub windows have a standard set of buttons ("->Main" which brings the main window to the front, "Print", "Events" which will show all events related to that sub-window, …). One of these buttons is "Close", which will simply close that window.

Is there a way to create a button that maps to the Windows "x" button, that I could set up as a resource once and then just bind to it?

Or is there a generic way to create the button without having to update each window's code behind.

I'm using Foddy Weaver, and Ninject. Also, there is a master View Model that most sub-windows map to (as there is shared status info shown on many of the sub-windows), if that helps (or complicates!).

What I have tried:

Tried this method : Closing a WPF Window using MVVM and minimal code-behind - jkshay.com[^] but it wasn't compiling (might be conflicting with the way I am currently doing RelayCommands per Angel6 examples)

Could never get "GetTemplateChild", searching for PART_CloseWindow (and some other names, don't remember now) to work.

Many of the relay command examples tie to a single variable, but this doesn't work for one View Model shared among several sub-windows (would close all of them)
Posted
Updated 20-Jun-20 12:42pm

You could create a base window class with the appropriate event handler in it, and derive all your actual windows from that base class. At that point, you can add a Click event handler in the XAML and simply point it at the base class handler method.

If you want to make it possible to override the handler in specific windows, simply make the handler in the base class virtual.
 
Share this answer
 
v2
I figured it out on my own, and here is what I did:

I created an Interface, called ICloseable, that will be used in the code-behind:
C#
namespace MyProgram.Interfaces
{
    public interface ICloseable
    {
        void Close();
    }
}

In my ApplicationViewModel.cs, I add a command to close the window:
C#
  ...
public ICommand CloseWindow_Command { get; private set; }
  ...
public ApplicationViewModel()
{
      ...
    CloseWindow_Command = new RelayCommand<ICloseable>(CloseWindow);
      ...
}
  ...
public void CloseWindow(ICloseable window)
{
    if (window != null)
    {
        window.Close();
    }
}
  ...

In a given window, I add the name of the window in the main declaration (unique value for each window), and add that name as a CommandParameter in the Close button (which calls the close command):
C#
<Window x:Class="MyProgram.Window1"
        x:Name="theWindow1"
        ... >

            ...
        <Button Height="16" Width="45" 
                Content="Close" FontSize="9"                           
                Command="{Binding AppVM.CloseWindow_Command}"
                CommandParameter="{Binding ElementName=theWindow1}"
                ToolTip="Close this window"/>
            ...

And here is the code-behind for the given window, adding the Interface ICloseable:
C#
namespace MyProgram
{
    public partial class Window1 : Window, ICloseable
    {
        public Window1()
        {
            public ApplicationViewModel AppVM = ApplicationViewModel.Instance;
            InitializeComponent();
        }
    }
}
 
Share this answer
 
Comments
pranjal mudholkar 3-Jun-22 17:18pm    
Works thanks!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900