1

I have two buttons Save, Save & Close in my window. If user clicks on Save, I am able to successfully save the details. I am unable to figure out on how to close window, when user clicks on Save & Close. Here is my code for Save

<telerik:RadButton x:Name="button_Save" Content="Save" Command="{Binding SaveProductCommand}" CommandParameter="{Binding ElementName=ProductName, Path=Text}" />

Here is my Relay Command.

public ICommand SaveProductCommand
{
  get 
  {
    return new RelayCommand<string>(SaveProductExecute);
  } 
 }

My First Question:

Can we pass one more parameter True or false for Save and Save&Close ? So that we can use only one Relay Command for both ?

Second Question:

How to close current Window after Saving ?

Chatra
  • 2,989
  • 7
  • 40
  • 73

3 Answers3

2

Good Question..the key here is to use Action.Take a look at my sample

We will try to keep coding to minimal..

Can we pass one more parameter True or false for Save and Save&Close ? So that we can use only one Relay Command for both ?

Since you havent mentioned how you are passing true or false I have included a Listbox which has two string items True and False.

If true is selected only one part of command will execute and if false is selected we will perform both the methods in the command.

  1. Create a view with Button and Listbox

      <ListBox x:Name="items">
        <System:String>True</System:String>
        <System:String>False</System:String>
      </ListBox>
    
    <Button Content="MyButton" Command="{Binding Path=MyCustomCommand}" 
    CommandParameter="{Binding SelectedItem,ElementName=items}"/> 
    
  2. Create ViewModel i.e MyViewModel.cs

    public class MyViewModel : INotifyPropertyChanged
    {
    
       public Action CloseAction { get; set; }
       public ICommand MyCustomCommand { get; set; }
    
    
       public MyViewModel()
       {
          MyCustomCommand = new RelayCommand(new Action<object>(MyFunction));
       }
    
    
       private void MyFunction(object MyCommandParameter)
       {
        if (Convert.ToString(MyCommandParameter) == "True")
        {
            MessageBox.Show("Save Executed");
        }
        else
        {
            MessageBox.Show("Save Execcuted");
            CloseAction();
        }
    }
    
  3. In View Codebehind

      public partial class MainWindow : Window
      {
         public MainWindow()
         {
            InitializeComponent();
            MyViewModel mv = new MyViewModel();
            this.DataContext = mv;
    
            if (mv.CloseAction == null)
                mv.CloseAction = new Action(() => this.Close());
          }
      }
    
Rohit
  • 10,056
  • 7
  • 50
  • 82
  • What is that listbox ? I dont have that, I have to determine true or false based on button click. How can I do that ? – Chatra Mar 24 '15 at 16:56
  • How will you determine if you want to execute both part of methods or only one method.Listbox is just an example – Rohit Mar 24 '15 at 16:57
  • Mine in UserControl not window. So, I am unable to get hold of this.Close() – Chatra Mar 24 '15 at 17:06
  • CloseAction(); this is throwing null reference exception. In fact I figured out how to close usercontrol window – Chatra Mar 24 '15 at 17:23
  • There is no such concept as "closing a control". And I don't think that such concept, if existed, could be of any use. You can: 1) hide the user control if it is no longer needed, maybe temporarily; 2) permanently remove the control from the logical tree. – Rohit Mar 24 '15 at 17:23
  • http://stackoverflow.com/questions/19317064/disconnecting-an-element-from-any-unspecified-parent-container-in-wpf – Rohit Mar 24 '15 at 17:30
  • public partial class MainWindow : Window this one looks as public partial class AddProduct : UserControl in .cs file. So, Am unable to get Close(). How can I get that ? – Chatra Mar 24 '15 at 17:33
0

to ans your 2 questions --

yes you can multi bind ... doing something like this ..

<Button.CommandParameter>
    <MultiBinding>
         <Binding Path="path" ElementName="elementName"/>
         <Binding Path="path2" ElementName="elementName2"/>
    </MultiBinding>
</Button.CommandParameter>

and there are many ways to close the window please have a look here and here

Community
  • 1
  • 1
Muds
  • 4,006
  • 5
  • 31
  • 53
0

Consider leveraging messaging with parameters to pass around data between your objects.

You can use an EventAggregator or MessageBus.

The idea is to have your user controls subscribe to events that they would like to respond to.

NOTE:

I do this with viewmodels. However, I think it is a code-smell when adding this code to user-controls that are meant to have general use regardless of the application employing them.

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);
    }
}
Scott Nimrod
  • 11,206
  • 11
  • 54
  • 118