Reputation: 3129
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 ?
Upvotes: 1
Views: 2952
Reputation: 10236
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.
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}"/>
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();
}
}
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());
}
}
Upvotes: 2
Reputation: 11595
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);
}
}
Upvotes: 0
Reputation: 4116
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
Upvotes: 0