[c#] WPF MVVM: How to close a window

I have a Button that closes my window when it's clicked:

<Button x:Name="buttonOk"  IsCancel="True">Ok</Button>

That's fine until I add a Command to the Button i.e.

<Button x:Name="buttonOk" 
        Command="{Binding SaveCommand}" 
        IsCancel="True">Ok</Button>

Now it doesn't close presumably because I am handling the Command. I can fix this by putting an EventHandler in and calling this.Close() i.e.

<Button x:Name="buttonOk" 
        Click="closeWindow" 
        Command="{Binding SaveCommand}" 
        IsCancel="True">Ok</Button>

but now I have code in my code behind i.e. the method SaveCommand. I am using the MVVM pattern and SaveCommand is the only code in my code behind.

How can I do this differently so as not to use code behind?

This question is related to c# .net wpf xaml mvvm

The answer is


I also had to deal with this problem, so here my solution. It works great for me.

1. Create class DelegateCommand

    public class DelegateCommand<T> : ICommand
{
    private Predicate<T> _canExecuteMethod;
    private readonly Action<T> _executeMethod;
    public event EventHandler CanExecuteChanged;

    public DelegateCommand(Action<T> executeMethod) : this(executeMethod, null)
    {
    }
    public DelegateCommand(Action<T> executeMethod, Predicate<T> canExecuteMethod)
    {
        this._canExecuteMethod = canExecuteMethod;
        this._executeMethod = executeMethod ?? throw new ArgumentNullException(nameof(executeMethod), "Command is not specified."); 
    }


    public void RaiseCanExecuteChanged()
    {
        if (this.CanExecuteChanged != null)
            CanExecuteChanged(this, null);
    }
    public bool CanExecute(object parameter)
    {
        return _canExecuteMethod == null || _canExecuteMethod((T)parameter) == true;
    }

    public void Execute(object parameter)
    {
        _executeMethod((T)parameter);
    }
}

2. Define your command

        public DelegateCommand<Window> CloseWindowCommand { get; private set; }


    public MyViewModel()//ctor of your viewmodel
    {
        //do something

        CloseWindowCommand = new DelegateCommand<Window>(CloseWindow);


    }
        public void CloseWindow(Window win) // this method is also in your viewmodel
    {
        //do something
        win?.Close();
    }

3. Bind your command in the view

public MyView(Window win) //ctor of your view, window as parameter
    {
        InitializeComponent();
        MyButton.CommandParameter = win;
        MyButton.Command = ((MyViewModel)this.DataContext).CloseWindowCommand;
    }

4. And now the window

  Window win = new Window()
        {
            Title = "My Window",
            Height = 800,
            Width = 800,
            WindowStartupLocation = WindowStartupLocation.CenterScreen,

        };
        win.Content = new MyView(win);
        win.ShowDialog();

so thats it, you can also bind the command in the xaml file and find the window with FindAncestor and bind it to the command parameter.


I've tried to resolve this issue in some generic, MVVM way, but I always find that I end up unnecessary complex logic. To achieve close behavior I have made an exception from the rule of no code behind and resorted to simply using good ol' events in code behind:

XAML:

<Button Content="Close" Click="OnCloseClicked" />

Code behind:

private void OnCloseClicked(object sender, EventArgs e)
{
    Visibility = Visibility.Collapsed;
}

Although I wish this would be better supported using commands/MVVM, I simply think that there is no simpler and more clear solution than using events.


Very clean and MVVM way is to use InteractionTrigger and CallMethodAction defined in Microsoft.Interactivity.Core

You will need to add a new namespace as below

xmlns:i="http://schemas.microsoft.com/xaml/behaviors"

You will need the Microsoft.Xmal.Behaviours.Wpf assembly and then the below xaml code will work.

<Button Content="Save" Command="{Binding SaveCommand}">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="Click">
      <i:CallMethodAction MethodName="Close"
                           TargetObject="{Binding RelativeSource={RelativeSource
                                                  Mode=FindAncestor,
                                                  AncestorType=Window}}" />
    </i:EventTrigger>
  </i:Interaction.Triggers>
</Button>

You don't need any code behind or anything else and can also call any other method of Window.


I'd personally use a behaviour to do this sort of thing:

public class WindowCloseBehaviour : Behavior<Window>
{
    public static readonly DependencyProperty CommandProperty =
      DependencyProperty.Register(
        "Command",
        typeof(ICommand),
        typeof(WindowCloseBehaviour));

    public static readonly DependencyProperty CommandParameterProperty =
      DependencyProperty.Register(
        "CommandParameter",
        typeof(object),
        typeof(WindowCloseBehaviour));

    public static readonly DependencyProperty CloseButtonProperty =
      DependencyProperty.Register(
        "CloseButton",
        typeof(Button),
        typeof(WindowCloseBehaviour),
        new FrameworkPropertyMetadata(null, OnButtonChanged));

    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public object CommandParameter
    {
        get { return GetValue(CommandParameterProperty); }
        set { SetValue(CommandParameterProperty, value); }
    }

    public Button CloseButton
    {
        get { return (Button)GetValue(CloseButtonProperty); }
        set { SetValue(CloseButtonProperty, value); }
    }

    private static void OnButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var window = (Window)((WindowCloseBehaviour)d).AssociatedObject;
        ((Button) e.NewValue).Click +=
            (s, e1) =>
            {
                var command = ((WindowCloseBehaviour)d).Command;
                var commandParameter = ((WindowCloseBehaviour)d).CommandParameter;
                if (command != null)
                {
                    command.Execute(commandParameter);                                                      
                }
                window.Close();
            };
        }
    }

You can then attach this to your Window and Button to do the work:

<Window x:Class="WpfApplication6.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:local="clr-namespace:WpfApplication6"
        Title="Window1" Height="300" Width="300">
    <i:Interaction.Behaviors>
        <local:WindowCloseBehaviour CloseButton="{Binding ElementName=closeButton}"/>
    </i:Interaction.Behaviors>
    <Grid>
        <Button Name="closeButton">Close</Button>
    </Grid>
</Window>

I've added Command and CommandParameter here so you can run a command before the Window closes.


I think the most simple way has not been included already (almost). Instead of using Behaviours which adds new dependencies just use attached properties:

    using System;
    using System.Windows;
    using System.Windows.Controls;

    public class DialogButtonManager
    {
        public static readonly DependencyProperty IsAcceptButtonProperty = DependencyProperty.RegisterAttached("IsAcceptButton", typeof(bool), typeof(DialogButtonManager), new FrameworkPropertyMetadata(OnIsAcceptButtonPropertyChanged));
        public static readonly DependencyProperty IsCancelButtonProperty = DependencyProperty.RegisterAttached("IsCancelButton", typeof(bool), typeof(DialogButtonManager), new FrameworkPropertyMetadata(OnIsCancelButtonPropertyChanged));

        public static void SetIsAcceptButton(UIElement element, bool value)
        {
            element.SetValue(IsAcceptButtonProperty, value);
        }

        public static bool GetIsAcceptButton(UIElement element)
        {
            return (bool)element.GetValue(IsAcceptButtonProperty);
        }

        public static void SetIsCancelButton(UIElement element, bool value)
        {
            element.SetValue(IsCancelButtonProperty, value);
        }

        public static bool GetIsCancelButton(UIElement element)
        {
            return (bool)element.GetValue(IsCancelButtonProperty);
        }

        private static void OnIsAcceptButtonPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            Button button = sender as Button;

            if (button != null)
            {
                if ((bool)e.NewValue)
                {
                    SetAcceptButton(button);
                }
                else
                {
                    ResetAcceptButton(button);
                }
            }
        }

        private static void OnIsCancelButtonPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            Button button = sender as Button;

            if (button != null)
            {
                if ((bool)e.NewValue)
                {
                    SetCancelButton(button);
                }
                else
                {
                    ResetCancelButton(button);
                }
            }
        }

        private static void SetAcceptButton(Button button)
        {
            Window window = Window.GetWindow(button);
            button.Command = new RelayCommand(new Action<object>(ExecuteAccept));
            button.CommandParameter = window;
        }

        private static void ResetAcceptButton(Button button)
        {
            button.Command = null;
            button.CommandParameter = null;
        }

        private static void ExecuteAccept(object buttonWindow)
        {
            Window window = (Window)buttonWindow;

            window.DialogResult = true;
        }

        private static void SetCancelButton(Button button)
        {
            Window window = Window.GetWindow(button);
            button.Command = new RelayCommand(new Action<object>(ExecuteCancel));
            button.CommandParameter = window;
        }

        private static void ResetCancelButton(Button button)
        {
            button.Command = null;
            button.CommandParameter = null;
        }

        private static void ExecuteCancel(object buttonWindow)
        {
            Window window = (Window)buttonWindow;

            window.DialogResult = false;
        }
    }

Then just set it on your dialog buttons:

<UniformGrid Grid.Row="2" Grid.Column="1" Rows="1" Columns="2" Margin="3" >
    <Button Content="Accept" IsDefault="True" Padding="3" Margin="3,0,3,0" DialogButtonManager.IsAcceptButton="True" />
    <Button Content="Cancel" IsCancel="True" Padding="3" Margin="3,0,3,0" DialogButtonManager.IsCancelButton="True" />
</UniformGrid>

In your current window xaml.cs file, call the below code:

var curWnd = Window.GetWindow(this); // passing current window context
curWnd?.Close();

This should do the thing.
It worked for me, hope will do the same for you )


For small apps, I use my own Application Controller for showing, closing and disposing windows and DataContexts. It's a central point in UI of an application.

It's something like this:

//It is singleton, I will just post 2 methods and their invocations
public void ShowNewWindow(Window window, object dataContext = null, bool dialog = true)
{
    window.DataContext = dataContext;
    addToWindowRegistry(dataContext, window);

    if (dialog)
        window.ShowDialog();
    else
        window.Show();

}

public void CloseWindow(object dataContextSender)
{
    var correspondingWindows = windowRegistry.Where(c => c.DataContext.Equals(dataContextSender)).ToList();
    foreach (var pair in correspondingWindows)
    {
        pair.Window.Close();              
    }
}

and their invocations from ViewModels:

// Show new Window with DataContext
ApplicationController.Instance.ShowNewWindow(
                new ClientCardsWindow(),
                new ClientCardsVM(),
                false);

// Close Current Window from viewModel
ApplicationController.Instance.CloseWindow(this);

Of course you can find some restrictions in my solution. Again: I use it for small projects, and it's enough. If you're interested, I can post full code here or somewhere else/


There is a useful behavior for this task which doesn't break MVVM, a Behavior, introduced with Expression Blend 3, to allow the View to hook into commands defined completely within the ViewModel.

This behavior demonstrates a simple technique for allowing the ViewModel to manage the closing events of the View in a Model-View-ViewModel application.

This allows you to hook up a behavior in your View (UserControl) which will provide control over the control's Window, allowing the ViewModel to control whether the window can be closed via standard ICommands.

Using Behaviors to Allow the ViewModel to Manage View Lifetime in M-V-VM

http://gallery.expression.microsoft.com/WindowCloseBehavior/

Above link has been archived to http://code.msdn.microsoft.com/Window-Close-Attached-fef26a66#content


The solution to close a window in wpf that that worked for me is not answered here so i thought i would add my solution too.

        private static Window GetWindow(DependencyObject sender)
        {
            Window window = null;
            if (sender is Window)
                window = (Window)sender;
            if (window == null)
                window = Window.GetWindow(sender);
            return window;
        }
        private void CloseWindow(object sender, RoutedEventArgs e)
        {
            var button = (Button)sender as DependencyObject;

            Window window = GetWindow(button);
                if (window != null)
                    window.Close();
                   // window.Visibility = Visibility.Hidden; 
           // choose between window.close or set window.visibility to close or hide the window.

            //            }
        }

Add CloseWindow event to the button in you window as following.

<Button Content="Cancel" Click="CloseWindow" >

I found myself having to do this on a WPF application based on .Net Core 3.0, where unfortunately behaviour support was not yet officially available in the Microsoft.Xaml.Behaviors.Wpf NuGet package.

Instead, I went with a solution that made use of the Façade design pattern.

Interface:

public interface IWindowFacade
{
    void Close();
}

Window:

public partial class MainWindow : Window, IWindowFacade
…

Standard command property on the view model:

public ICommand ExitCommand
…

Control binding:

<MenuItem Header="E_xit" Command="{Binding ExitCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"/>

Command:

public class ExitCommand : ICommand
{
    …
    public void Execute(object parameter)
    {
        var windowFacade = parameter as IWindowFacade;
        windowFacade?.Close();
    }
    …
}

Because the Close() method is already implemented by the Window class, applying the façade interface to the window is the only required code behind in the UI layer (for this simple example). The command in the presentation layer avoids any dependencies on the view/UI layer as it has no idea what it is talking to when it calls the Close method on the façade.


Simple approach is close window on saveComand Implementation. Use below code to close window.

Application.Current.Windows[1].Close();

It will close the child window.


As someone commented, the code I have posted is not MVVM friendly, how about the second solution?

1st, not MVVM solution (I will not delete this as a reference)

XAML:

<Button Name="okButton" Command="{Binding OkCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}">OK</Button>

ViewModel:

public ICommand OkCommand
{
    get
    {
        if (_okCommand == null)
        {
            _okCommand = new ActionCommand<Window>(DoOk, CanDoOk);
        }
        return _okCommand ;
    }
}

void DoOk(Window win)
{
    // Your Code
    win.DialogResult = true;
    win.Close();
}

bool CanDoOk(Window win) { return true; }

2nd, probably better solution: Using attached behaviours

XAML

<Button Content="Ok and Close" Command="{Binding OkCommand}" b:CloseOnClickBehaviour.IsEnabled="True" />

View Model

public ICommand OkCommand
{
    get { return _okCommand; }
}

Behaviour Class Something similar to this:

public static class CloseOnClickBehaviour
{
    public static readonly DependencyProperty IsEnabledProperty =
        DependencyProperty.RegisterAttached(
            "IsEnabled",
            typeof(bool),
            typeof(CloseOnClickBehaviour),
            new PropertyMetadata(false, OnIsEnabledPropertyChanged)
        );

    public static bool GetIsEnabled(DependencyObject obj)
    {
        var val = obj.GetValue(IsEnabledProperty);
        return (bool)val;
    }

    public static void SetIsEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsEnabledProperty, value);
    }

    static void OnIsEnabledPropertyChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs args)
    {
        var button = dpo as Button;
        if (button == null)
            return;

        var oldValue = (bool)args.OldValue;
        var newValue = (bool)args.NewValue;

        if (!oldValue && newValue)
        {
            button.Click += OnClick;
        }
        else if (oldValue && !newValue)
        {
            button.PreviewMouseLeftButtonDown -= OnClick;
        }
    }

    static void OnClick(object sender, RoutedEventArgs e)
    {
        var button = sender as Button;
        if (button == null)
            return;

        var win = Window.GetWindow(button);
        if (win == null)
            return;

        win.Close();
    }

}

I have following solution in Silverlight. Would also be in WPF.

ChildWindowExt.cs:

namespace System.Windows.Controls
{
    public class ChildWindowExt : ChildWindow
    {
        public static readonly DependencyProperty IsOpenedProperty =
          DependencyProperty.Register(
          "IsOpened",
          typeof(bool),
          typeof(ChildWindowExt),
          new PropertyMetadata(false, IsOpenedChanged));

        private static void IsOpenedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if ((bool)e.NewValue == false)
            {
                ChildWindowExt window = d as ChildWindowExt;
                window.Close();
            }
            else if ((bool)e.NewValue == true)
            {
                ChildWindowExt window = d as ChildWindowExt;
                window.Show();
            }
        }

        public bool IsOpened
        {
            get { return (bool)GetValue(IsOpenedProperty); }
            set { SetValue(IsOpenedProperty, value); }
        }

        protected override void OnClosing(ComponentModel.CancelEventArgs e)
        {
            this.IsOpened = false;
            base.OnClosing(e);
        }

        protected override void OnOpened()
        {
            this.IsOpened = true;
            base.OnOpened();
        }
    }
}

ItemWindow.xaml:

<extControls:ChildWindowExt  
    x:Class="MyProject.ItemWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:extControls="clr-namespace:System.Windows.Controls"
    Title="{Binding Title}" IsOpened="{Binding IsOpened, Mode=TwoWay}" Width="640" Height="480">

    <Grid x:Name="LayoutRoot">
        <Button Command="{Binding UpdateCommand}" Content="OK" Width="70" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    </Grid>

</extControls:ChildWindowExt>

ItemViewModel.cs:

private bool _IsOpened;
public bool IsOpened
{
    get
    {
        return _IsOpened;
    }
    set
    {
        if (!Equals(_IsOpened, value))
        {
            _IsOpened = value;
            RaisePropertyChanged("IsOpened");
        }
    }
}

private RelayCommand _UpdateCommand;
/// <summary>
/// Insert / Update data entity
/// </summary>
public RelayCommand UpdateCommand
{
    get
    {
        if (_UpdateCommand == null)
        {
            _UpdateCommand = new RelayCommand(
                () =>
                {
                    // Insert / Update data entity
                    ...

                    IsOpened = false;
                },
                () =>
                {
                    return true;
                });
        }
        return _UpdateCommand;
    }
}

ItemsViewModel.cs:

    private RelayCommand _InsertItemCommand;
    /// <summary>
    /// 
    /// </summary>
    public RelayCommand InsertItemCommand
    {
        get
        {
            if (_InsertItemCommand == null)
            {
                _InsertItemCommand = new RelayCommand(
                    () =>
                    {
                        ItemWindow itemWin = new ItemWindow();
                        itemWin.DataContext = new ItemViewModel();
                        itemWin.Show();

                        // OR

                        // ItemWindow itemWin = new ItemWindow();
                        // ItemViewModel newItem = new ItemViewModel();
                        // itemWin.DataContext = newItem;
                        // newItem.IsOpened = true;

                    },
                    () =>
                    {
                        return true;
                    });
            }
            return _InsertItemCommand;
        }
    }

MainPage.xaml:

<Grid x:Name="LayoutRoot">
    <Button Command="{Binding InsertItemCommand}" Content="Add New" Width="70" HorizontalAlignment="Left" VerticalAlignment="Center" />
</Grid>

I wish you all good ideas and projects ;-)


I just completed a blog post on this very topic. In a nutshell, add an Action property to your ViewModel with get and set accessors. Then define the Action from your View constructor. Finally, invoke your action in the bound command that should close the window.

In the ViewModel:

public Action CloseAction  { get; set;}

and in the View constructor:

private View()
{
    InitializeComponent();
    ViewModel vm = new ViewModel();
    this.DataContext = vm;
    if ( vm.CloseAction == null )
        vm.CloseAction = new Action(this.Close);
}

Finally, in whatever bound command that should close the window, we can simply invoke

CloseAction(); // Calls Close() method of the View

This worked for me, seemed like a fairly elegant solution, and saved me a bunch of coding.


I struggled with this topic for some time, and eventually went with the simplest approach that is still consistent with MVVM: Have the button execute the Command that does all the heavy lifting and have the button's Click handler close the window.

XAML

<Button x:Name="buttonOk" 
        Click="closeWindow" 
        Command="{Binding SaveCommand}" />

XAML.cs

public void closeWindow() 
{
    this.DialogResult = true;
}

SaveCommand.cs

 // I'm in my own file, not the code-behind!

True, there is still code-behind, but there isn't anything inherently bad about that. And it makes the most sense to me, from an OO perspective, to just tell the window to close itself.


We have the name property in the .xaml definition:

x:Name="WindowsForm"

Then we have the button:

<Button Command="{Binding CloseCommand}" 
CommandParameter="{Binding ElementName=WindowsForm}" />

Then in the ViewModel:

public DelegateCommand <Object>  CloseCommand { get; private set; }

Constructor for that view model:
this.CloseCommand = new DelegateCommand<object>(this.CloseAction);

Then at last, the action method:

private void CloseAction (object obj)
{
  Window Win = obj as Window;
  Win.Close();

}

I used this code to close a pop-up window from an application..


You can do it without code behind. Create command, in Execute method call "Save" method on viewmodel and after that call close method on edit window, which you can pass to the command by parameter:

public void Execute(object parameter)
{
    _mainViewModel.SaveSomething();
    var editWindow = parameter as MyEditWindow;
    editWindow?.Close();
}

Save&Close button XAML:

<Button Content"Save&Close" Command="{Binding SaveCmd}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"  IsDefault="True" />

I've been searching for a solution to the same problem and found that doing following works fine. The solution is similar to what OP has mentioned in his question with some differences:

  1. No need of IsCancel property.

  2. Code behind should not close window. Just set DialogResult

In my case it first executes code behind and then view model command bound to the button.

XAML

<Button x:Name="buttonOk" Click="Save_Click" Command="{Binding SaveCommand}">OK</Button>

Code Behind

private void Apply_OnClick(object sender, RoutedEventArgs e)
{
    this.DialogResult = true;
}

View Model

private void Save()
{
 // Save data.
}

Hope this helps.


You could rephrase the question, and by doing so - coming up with another solution. How can I enable communication between views, viewmodels and whatnot in an MVVM environment? You could use the Mediator pattern. It's basically a notification system. For the actual Mediator implementation, google for it or ask me and I can email it.

Make a Command whose purpose is to close the view.

public void Execute( object parameter )
{
    this.viewModel.DisposeMyStuff();
    Mediator.NotifyColleagues(Mediator.Token.ConfigWindowShouldClose);
}

The Mediator will raise a notification (a token)

Listen to this notification (token) like this in the View codebehind constructor:

public ClientConfigView()
{
    InitializeComponent();
    Mediator.ListenOn(Mediator.Token.ConfigWindowShouldClose, callback => this.Close() );
}

This might helps you, closing a wpf window using mvvm with minimal code behind: http://jkshay.com/closing-a-wpf-window-using-mvvm-and-minimal-code-behind/


I use the Publish Subscribe pattern for complicated class-dependencies:

ViewModel:

    public class ViewModel : ViewModelBase
    {
        public ViewModel()
        {
            CloseComand = new DelegateCommand((obj) =>
                {
                    MessageBus.Instance.Publish(Messages.REQUEST_DEPLOYMENT_SETTINGS_CLOSED, null);
                });
        }
}

Window:

public partial class SomeWindow : Window
{
    Subscription _subscription = new Subscription();

    public SomeWindow()
    {
        InitializeComponent();

        _subscription.Subscribe(Messages.REQUEST_DEPLOYMENT_SETTINGS_CLOSED, obj =>
            {
                this.Close();
            });
    }
}

You can leverage Bizmonger.Patterns to get the MessageBus.

MessageBus

public class MessageBus
{
    #region Singleton
    static MessageBus _messageBus = null;
    private MessageBus() { }

    public static MessageBus Instance
    {
        get
        {
            if (_messageBus == null)
            {
                _messageBus = new MessageBus();
            }

            return _messageBus;
        }
    }
    #endregion

    #region Members
    List<Observer> _observers = new List<Observer>();
    List<Observer> _oneTimeObservers = new List<Observer>();
    List<Observer> _waitingSubscribers = new List<Observer>();
    List<Observer> _waitingUnsubscribers = new List<Observer>();

    int _publishingCount = 0;
    #endregion

    public void Subscribe(string message, Action<object> response)
    {
        Subscribe(message, response, _observers);
    }

    public void SubscribeFirstPublication(string message, Action<object> response)
    {
        Subscribe(message, response, _oneTimeObservers);
    }

    public int Unsubscribe(string message, Action<object> response)
    {
        var observers = new List<Observer>(_observers.Where(o => o.Respond == response).ToList());
        observers.AddRange(_waitingSubscribers.Where(o => o.Respond == response));
        observers.AddRange(_oneTimeObservers.Where(o => o.Respond == response));

        if (_publishingCount == 0)
        {
            observers.ForEach(o => _observers.Remove(o));
        }

        else
        {
            _waitingUnsubscribers.AddRange(observers);
        }

        return observers.Count;
    }

    public int Unsubscribe(string subscription)
    {
        var observers = new List<Observer>(_observers.Where(o => o.Subscription == subscription).ToList());
        observers.AddRange(_waitingSubscribers.Where(o => o.Subscription == subscription));
        observers.AddRange(_oneTimeObservers.Where(o => o.Subscription == subscription));

        if (_publishingCount == 0)
        {
            observers.ForEach(o => _observers.Remove(o));
        }

        else
        {
            _waitingUnsubscribers.AddRange(observers);
        }

        return observers.Count;
    }

    public void Publish(string message, object payload)
    {
        _publishingCount++;

        Publish(_observers, message, payload);
        Publish(_oneTimeObservers, message, payload);
        Publish(_waitingSubscribers, message, payload);

        _oneTimeObservers.RemoveAll(o => o.Subscription == message);
        _waitingUnsubscribers.Clear();

        _publishingCount--;
    }

    private void Publish(List<Observer> observers, string message, object payload)
    {
        Debug.Assert(_publishingCount >= 0);

        var subscribers = observers.Where(o => o.Subscription.ToLower() == message.ToLower());

        foreach (var subscriber in subscribers)
        {
            subscriber.Respond(payload);
        }
    }

    public IEnumerable<Observer> GetObservers(string subscription)
    {
        var observers = new List<Observer>(_observers.Where(o => o.Subscription == subscription));
        return observers;
    }

    public void Clear()
    {
        _observers.Clear();
        _oneTimeObservers.Clear();
    }

    #region Helpers
    private void Subscribe(string message, Action<object> response, List<Observer> observers)
    {
        Debug.Assert(_publishingCount >= 0);

        var observer = new Observer() { Subscription = message, Respond = response };

        if (_publishingCount == 0)
        {
            observers.Add(observer);
        }
        else
        {
            _waitingSubscribers.Add(observer);
        }
    }
    #endregion
}

}

Subscription

public class Subscription
{
    #region Members
    List<Observer> _observerList = new List<Observer>();
    #endregion

    public void Unsubscribe(string subscription)
    {
        var observers = _observerList.Where(o => o.Subscription == subscription);

        foreach (var observer in observers)
        {
            MessageBus.Instance.Unsubscribe(observer.Subscription, observer.Respond);
        }

        _observerList.Where(o => o.Subscription == subscription).ToList().ForEach(o => _observerList.Remove(o));
    }

    public void Subscribe(string subscription, Action<object> response)
    {
        MessageBus.Instance.Subscribe(subscription, response);
        _observerList.Add(new Observer() { Subscription = subscription, Respond = response });
    }

    public void SubscribeFirstPublication(string subscription, Action<object> response)
    {
        MessageBus.Instance.SubscribeFirstPublication(subscription, response);
    }
}

Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to .net

You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to use Bootstrap 4 in ASP.NET Core No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization .net Core 2.0 - Package was restored using .NetFramework 4.6.1 instead of target framework .netCore 2.0. The package may not be fully compatible Update .NET web service to use TLS 1.2 EF Core add-migration Build Failed What is the difference between .NET Core and .NET Standard Class Library project types? Visual Studio 2017 - Could not load file or assembly 'System.Runtime, Version=4.1.0.0' or one of its dependencies Nuget connection attempt failed "Unable to load the service index for source" Token based authentication in Web API without any user interface

Examples related to wpf

Error: the entity type requires a primary key Reportviewer tool missing in visual studio 2017 RC Pass command parameter to method in ViewModel in WPF? Calling async method on button click Setting DataContext in XAML in WPF How to resolve this System.IO.FileNotFoundException System.Windows.Markup.XamlParseException' occurred in PresentationFramework.dll? Binding an Image in WPF MVVM How to bind DataTable to Datagrid Setting cursor at the end of any text of a textbox

Examples related to xaml

Setting DataContext in XAML in WPF Change color of Button when Mouse is over Implement Validation for WPF TextBoxes Use StringFormat to add a string to a WPF XAML binding How to format number of decimal places in wpf using style/template? How to set DataGrid's row Background, based on a property value using data bindings WPF C# button style How to clear a textbox once a button is clicked in WPF? Add Items to Columns in a WPF ListView Binding ConverterParameter

Examples related to mvvm

Vue.js—Difference between v-model and v-bind Pass command parameter to method in ViewModel in WPF? [Vue warn]: Cannot find element Binding an Image in WPF MVVM Binding ComboBox SelectedItem using MVVM What is difference between MVC, MVP & MVVM design pattern in terms of coding c# How to make all controls resize accordingly proportionally when window is maximized? Add directives from directive in AngularJS Wpf DataGrid Add new row Close Window from ViewModel