RelayCommand RaiseCanExecuteChanged() fails - c#

I am using a couple of Buttons bound to RelayCommands initialized with CanExecute delegates.
RelayCommand DeleteCommand;
bool CanDelete()
{
return BoolProp1 && BoolProp2;
}
...
DeleteCommand = new RelayCommand(Delete, CanDelete);
BoolProp1 and BoolProp2 are regular properties with setters correctly raising PropertyChanged, but as we all know, this is not enough to make SL reevaluate CanExecute on commands. That's why i also call Delete.RaiseCanExecuteChanged() in both setters.
All this works fine (buttons are disabled and enabled properly) up to some point, where is all stops. At that point, calling Delete.RaiseCanExecuteChanged() no longer fires my breakpoints in CanDelete() and buttons forever stay the way they were.
I spend 2 hours trying to isolate the exact cause with no effect. I suspect multiple RaiseCanExecuteChanged() calls during single "binding iteration" somehow break the mechanism.
Any hints? I'm already considering using an additional IsExecutable field refreshed through INotifyPropertyChanged...
UPDATE
RelayCommand is actually GalaSoft.MvvmLight.Command.RelayCommand from MVVM Light Toolkit. ILSpy shows a pretty trivial implementation of ICommand:
public bool CanExecute(object parameter)
{
return this._canExecute == null || this._canExecute.Invoke();
}
public void RaiseCanExecuteChanged()
{
EventHandler canExecuteChanged = this.CanExecuteChanged;
if (canExecuteChanged != null)
{
canExecuteChanged.Invoke(this, EventArgs.Empty);
}
}
with _canExecute being a Func<bool> set once to the value passed to constructor.
I am still working to minimally reproduce the issue.
UPDATE
See my answer.

PEBKAC. My framework in certain cases ran the code
DeleteCommand = new RelayCommand(Delete, CanDelete);
more then once, overwriting commands that were actually bound to view with new instances.
If somebody has this problem - make sure you're calling RelayCommand.RaiseCanExecuteChanged() on the same instance that the view is bound to.

For anyone else who faced the same issue and the accepted answer didn't help me (and for my own record, as I spent a few hours today with it).
If you're using MVVM Light in a VSTO add-in, make sure that the Office application gets a chance to process its own messages to get this to work. For example, in my case I had my Ribbon buttons listening to CanExecuteChanged of underlying VM's command objects, which would not fire no matter what I did. After spending a few hours, I realized that I had to let Office application take a breath and process incoming message to allow CanExecuteChanged to be caught by the add-in. What I then did was to hand over my RaiseCanExecuteChanged function to DispatcherHelper to let it fire asynchronously. It was only then that my Ribbon buttons started reacting to CanExecuteChanged events. Something like this:
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
doc.Activate();
ResetVariablesCommand.RaiseCanExecuteChanged();
});

Related

WPF CanExecute depending on more that one factor

I am facing a dilemma in using the CanExecute parameter in CommandBinding for the menu in my application.
The situation is following: the application itself can run in certain modes, e.g. the working mode, review mode, etc. Depending on the mode, some menu items should be enabled or not (hence, should be possible to execute or not).
What I've done until now is create 4 event handlers for CanExecute:
private void Mode1CanExecute(object sender, CanExecuteRoutedEventArgs e);
private void Mode1CannotExecute(object sender, CanExecuteRoutedEventArgs e);
private void Mode2CanExecute(object sender, CanExecuteRoutedEventArgs e);
private void Mode2CannotExecute(object sender, CanExecuteRoutedEventArgs e);
as some menu commands are common to both modes, some are exclusive to each mode.
As the application develops, there are more factors determining whether a particular menu command should be executed at the moment. The solutions I can think of are:
adding a boolean multibinding to CanExecute event handler, but I couldn't find any examples of this solution, I believe it is not possible.
adding more event handlers for CanExecute with even longer names, what will actually make the code less readable
have "per menu item" CanExecute event handler and base the code for each event handler on some boolean variables to determine the result of it
I know that enabling the menu item can be done in SubmenuOpened event handler, but for many of the commands there is also a KeyGesture defined.
My question is: what would be the best practice in this case, so the logic of the application (command execution availability) is guaranteed but also the code readability stays on reasonable level?
Thank you for any suggestions.
Well what I do - is I always have 1 canexecute method per command
This way it's simple and consistent and You know where to look for problem
Another point to have it in 1 method - is just pure testability and readability.
Very simple to test then
public bool CanExecuteGoCommand(){
if (xxx)
return true;
else
return false;
}
and the method can be as big as You want, with as many If's as You need with a million conditions, modes, variables ect..
What I would do is use an implementation of DelegateCommand or RelayCommand as your ICommand property in your ViewModel. Either of these will allow you to pass a Func into the constructor of the ICommand instance as the 'CanExecute' delegate. When you pass this Func in, you could include other properties of your ViewModel as closures, and therefore access them in the delegate. This will allow you to combine your CanExecute parameter with any other member in your ViewModel.

"An ItemsControl is inconsistent with its items source" thrown when calling MessageBox.Show()

I'm extremely new to WPF and I have the following problem:
I'm trying to develop a practice application to help me have control of my budgets.
I have a class Partida like so:
public class Partida
{
public delegate void PartidaChangedHandler(Partida p);
public event PartidaChangedHandler OnPartidaChanged;
private ObservableCollection<PartidaEntry> content;
public Partida()
{
content = new ObservableCollection<PartidaEntry>();
content.CollectionChanged += PartidaEntriesCollectionChanged;
}
public void PartidaEntriesCollectionChanged(object s, NotifyCollectionChangedEventArgs args)
{
if (OnPartidaChanged != null)
{
OnPartidaChanged(this);
}
}
}
I'm displaying the content collection with a Datagrid, but I need to know when the content collection of this class changed and fire the OnPartidaChanged event.
Outside of the class (in MainWindow) I hook up to the OnPartidaChanged event like so:
p.OnPartidaChanged += (Partida ppp) =>
{
int foo = 5;
MessageBox.Show("A partida has changed!");
};
When I add a new row within the DataGrid, the event fires correctly, however as soon as MessageBox gets executed I get an InvalidOperationException with the following message:
An ItemsControl is inconsistent with its items source.
Any idea how can a fix that problem without losing the ability to listen to the ObservableCollection's CollectionChanged event and firing OnPartidaChanged after that event?
Thanks in advance!
P.S.: Also, I would like to know what on earth MessageBox has to do with ItemControl... why is the exception firing if MessageBox only displays a simple box! :S
The answer in WPF add item to datagrid bound to observablecollection exception explains clearly exactly what is happening: the event handler is being called while the operation that is changing the collection is in progress, and calling MessageBox.Show() gives the dispatcher message-handling loop a chance to start processing messages again. This causes re-entrancy that is incompatible with the way WPF works: the collection-changing operation has not been completely resolved, but the UI is being given a chance to try to run the logic that should not be run until after that operation has been completely resolved.
In other words, just as the exception states, the control is in an inconsistent state, because it was allowed to do some processing that should not have occurred until after it was completely done dealing with the collection changing.
I grant that the advice in the other answer is not terribly compelling. It is reasonable advice as far as it goes, but offers no real alternatives.
In your scenario, without changing anything else about your implementation, one obvious solution is to defer the message box until after the collection-changing operation has been completely resolved. You can do this by using the Dispatcher.InvokeAsync() method to defer execution of the call to MessageBox.Show():
p.OnPartidaChanged += (Partida ppp) =>
{
int foo = 5;
Dispatcher.InvokeAsync(() => MessageBox.Show("A partida has changed!"));
};
Of course, there is the question as to whether showing a message box is really the best way to handle the event. It's not really clear from the limited information in your question why your event handler looks the way it does. If you are sure that showing a message box every time the collection changes is really the right thing to do, the above should resolve your problem.
But you might want to consider alternative means of presenting the information to the user, such as displaying it in a status field in the UI, or even providing some kind of log of events e.g. in a multi-line text box or list-box. These kinds of approaches will generally involve data-binding that fit within the normal flow of event and data handling in WPF, and would work as synchronous code without running into the issue you're seeing here.

Forcing Reevaluation on ICommand.CanExecute

In WPF XAML, I've got a Button's Command property working with an implementation of a class implementing ICommand.
In this implementation, I don't have my CanExecuteChanged event wired up to use CommandManager.RequerySuggested - I want to have control over when CanExecute is called, and using this calls it way more often than necessary.
The only other way I can get ICommand.CanExecute to re-evaluate is to use something like:
public void InvokeCanExecute()
{
CanExecuteChanged.Invoke(this, new EventArgs());
}
In my class implementing the ICommand.
This seems really nasty - am I missing something obvious? I've tried invoking the re-evaluation using PropertyChanged but that doesn't seem to work.
It's true that - if you don't want to use CommandManager.RequerySuggested, which indeed might call CanExecute more often than necessary - you need to explicitly invoke your own InvokeCanExecute method in order to force the command to re-evaluate its CanExecute condition.
However, in most cases the CanExecute condition will depend on public (bindable) properties, meaning properties that raise the PropertyChanged event to indicate that their value has changed - it is possible to hook into this event, in order to automatically call InvokeCanExecute whenever one of the properties the command depends on has changed. For an example of how to implement such a command, see this guy's blog post (if I'm not mistaken, this approach is implemented e.g. as part of the MVVM Light toolkit).
Instantiating a command using this approach would look somewhat like the following:
SaveCommand = new RelayCommand(() => { /* do some stuff; */ },
() => !string.IsNullOrEmpty(Name),
this, () => Name);
Since the command's CanExecute condition (which checks whether Name is empty) depends on the Name property, it needs to be re-evaluated whenever Name's content changes. You simply pass a reference to the Name property to the command's constructor, and InvokeCanExecute will automatically be called whenever the value of Name changes.
In theory, it is possible to go one step further and let the command itself check on which properties it depends - if you're interested in this approach, check out
one of my blog articles, but note that this one heavily depends on reflection so it always depends on the detailed use-case whether this approach is feasible or not. A sample implementation of this solution is included in the MVVMbasics framework (disclaimer: published by me). In this case, you could reduce the command initialization code to:
SaveCommand = CreateRelayCommand(() => { /* do some stuff; */ },
() => !string.IsNullOrEmpty(Name));
No, you are not really missing anything. Here's a similar question that recommends the same approach you're taking: What is the actual task of CanExecuteChanged and CommandManager.RequerySuggested?.
You can make your method a little bit more robust though:
public void InvokeCanExecute()
{
var handler = CanExecuteChanged;
if (handler != null)
{
handler(this, new EventArgs());
}
}

Dispatch all methods in class C# [duplicate]

I'm a web and backend programmer by nature. Normally I try to avaoid making windows programs. Now I have to make a WPF client.
I have a background task that raises an event every often time. (It is working like a poller and when the criteria are met an event is raised). Noob as I am I wrote this code that was attached to the event to update the UI.
private void IsDisconnectedEvent()
{
UserWindow.Visibility = Visibility.Hidden;
DisconnectWindow.Visibility = Visibility.Visible;
}
This gives an exception because I am not on the same thread. After some googling I found that I should change the code with:
private void IsDisconnectedEvent()
{
Dispatcher.Invoke(() =>
{
UserWindow.Visibility = Visibility.Hidden;
DisconnectWindow.Visibility = Visibility.Visible;
});
}
This works, but this is not the only event and thus makes my code horrible ugly. Are there better ways to do this?
Regarding this:
This works, but this is not the only event and thus makes my code
horrible ugly
Yes, your WPF-based code will definitely be extremely horrible unless you understand and embrace The WPF Mentality.
Basically, all interactions between your custom logic (AKA Business logic or Application Logic) and the WPF UI should manifest in the form of Declarative DataBinding as opposed to the traditional imperative approach.
This means that there should be nothing like this:
UserWindow.Visibility = Visibility.Hidden;
anywhere in your code, simply because introducing things like that makes your code dependent on the UI and thus only executable on the UI thread.
Instead, the WPF approach to that would be to declaratively DataBind the Visibility propety of the UI element (IN XAML) to a relevant bool property that you can operate from the outside, like this:
<UserWindow Visibility="{Binding ShowUserWindow, Converter={my:BoolToVisibilityConverter}}">
<!-- ... -->
</UserWindow>
Then, you would need to create a relevant class that contains the properties the UI is expecting to bind to. This is called a ViewModel.
Notice that in order to properly support Two-Way WPF DataBinding, your ViewModels must Implement the INotifyPropertyChanged interface.
When doing so, it is also convenient to have the PropertyChanged event from that interface marshalled to the UI thread, so that you no longer have to worry about setting the ViewModel's properties by using the Dispatcher.
Therefore our first step is to have all our ViewModels inherit from a class like this:
(taken from this answer):
public class PropertyChangedBase:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
//Raise the PropertyChanged event on the UI Thread, with the relevant propertyName parameter:
Application.Current.Dispatcher.BeginInvoke((Action) (() =>
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}));
}
}
Once we have our Property Change Notification Dispatch to the UI Thread in place, we can proceed to create a relevant ViewModel that suits, in this case, the UserWindow and it's DataBinding expectations:
public class UserViewModel: PropertyChangedBase
{
private bool _showUserWindow;
public bool ShowUserWindow
{
get {return _showUserWindow; }
set
{
_showUserWindow = value;
OnPropertyChanged("ShowUserWindow"); //This is important!!!
}
}
}
Finally, you would need to set the Window's DataContext to an instance of it's corresponding ViewModel. One simple way to do that is in the Window's constructor:
public UserWindow() //Window's Constructor
{
InitializeComponent(); //this is required.
DataContext = new UserViewModel(); //here we set the DataContext
}
As you can see in this example, there is literally no need to manipulate the UI element's properties in procedural code. This is good not only because it resolves the Thread Affinity issues (because now you can set the ShowUserWindow property from any thread), but also because it makes your ViewModels and logic completely decoupled from the UI and thus testable and more scalable.
This same concept applies to EVERYTHING in WPF.
One detail that I need to mention is that I'm making use of a technique of Combining MarkupExtension and IValueConverter in order to reduce the the XAML boilerplate involved in using Converters.
You can read more about that in the link and also the MSDN DataBinding page linked above.
Let me know if you need further details.

How to deal with sequential calling event handlers?

Before I reinvent the wheel...
This is just an EXAMPLE for describing the problem -- let's say you have a backend with collection of some data, and frontend which displays one item of the collection.
At the backend I have ItemIndex -- whenever it changes, it fires up OnScroll event.
I also have AddNewItem method, it adds new item at the end of the collection. The end of the method is calling OnNewItem event handler.
And here is the catch -- in AddNewItem I have to change ItemIndex, which fires OnScroll. One of the receivers of both (!) OnScroll and OnNewItem if frontend which displays selected item.
In such case it is called twice (not good). One solution would be altering item_index instead of ItemIndex, and this way preventing OnScroll, but I don't like it because ItemIndex does not act as black box anymore.
Is there any established pattern for sequential firing events, and sending only "important" ones (here: OnNewItem overrides OnScroll)? My idea would be to define an event scope, then instead of sending events directly, just register them for sending, and at the close of scope sort them and send the required ones.
In general -- question -- how should I deal with potential sequential event triggering. Use internals to avoid sending redundant events? Ignore the overhead? ...?
The answer seems obvious to me athough I could have easily missed something:
private bool IsAdding { get; set; }
private int item_index;
private IList m_collection;
public void AddNewItem(object item)
{
if (item == null)
{
throw new Exception("Cannot add null item."); // little bit of contracting never hurts
}
m_collection.Add(item);
IsAdding = true;
ItemIndex = collection.Count - 1; //I'm just making assumptions about this piece but it is not important how you decide what your index is to answer the question
if (OnNewItem != null)
{
OnNewItem(this, EventArgs.Empty);
}
}
public int ItemIndex
{
get { return item_index =; }
set
{
item_index = value;
if (!IsAdding && OnScroll != null) //won't double fire event thanks to IsAdding
{
OnScroll(this, EventArgs.Empty);
}
IsAdding = false; //need to reset it
}
}
One thing I would note is that you made mention of just simply altering item_index directly but that wouldn't have a blackbox behavior. Well black box is all well and good ... but that term only applies to objects interacting with this class we have been discussing.
You should feel empowered to use the internals of your class within itself. It is not good OOP to blackbox items within itself. If you are doing that then your class probably has design issues where it should be split into multiple classes.
One solution is to use a 'latch' of some form. When updating, you perform your UI actions via a helper which sets a flag saying 'hey, I'm in a special state!'. Then, when raising events, you check to see if the latch is set -- if it is, you skip raising those events.
It's basically a very simple, generalised version of what Matthew posted. Depending on the situation, setting a flag may be more than adequate.
Jeremy Miller's explanation is worth reading
You could point both events at a single function. The function can determine the sender and perform the appropriate action(s).

Categories

Resources