I want to re-trigger the canExecute functionality from a DelegateCommand after some modifications have been made by the user. How do I do this?
The event CanExecuteChanged of the interface ICommand must be raised to re-trigger call of the CanExecute method.
Create a public method "RaiseCanExecuteChanged" in the DelegateCommand which fires the event.
Related
I am working on an editor plugin and now implementing support for code hovers.
I have extended AbstractInformationControl (and implemented IInformationControlExtension2) to create a new control for showing the hover info.
It works almost fine, but I am unable to receive property change events in my information control. What I try is like this, but the event handler does not fire:
public class MyHoverInfoControl extends AbstractInformationControl implements IInformationControlExtension2 {
public MyHoverInfoControl(Shell parentShell, String string) {
super(parentShell, string);
create();
Activator.getDefault().getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent event) {
// TODO Auto-generated method stub
}
});
}
The control itself contains a StyledText. I have also tried to add a KeyListener to this StyledText to see if key events are received, and it only seemed to work if I click into the control (it is not enough to hover over a text to show the control). But property change event does not seem to be received even after the click.
Is it possible to receive property change events for an AbstractInformationControl subclass?
In Xamarin Forms, I created a bindable property like so:
public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create("SelectedItem", typeof(MyItem), typeof(MyGrid), default(MyItem));
public MyItem SelectedItem
{
get { return (MyItem)GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
Here's my constructor:
public MyView()
{
InitializeComponent();
PropertyChanged += OnPropertyChanged;
}
protected void OnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
if (propertyChangedEventArgs.PropertyName == "SelectedItem")
{
// called twice
}
}
Can somebody explain why property changed event is firing twice? If I create a changed handler in the definition of the bindable property, then the handler is called once.
public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create("SelectedItem", typeof(MyItem), typeof(MyGrid), default(MyItem), null, SelectedItemChanged);
I have noticed the issue exists only in code-behind. If I set the property directly in XAML, property changed event fires once.
We don't really have enough information to answer this question with certainty, but I can speculate.
Without seeing your SetValue method, my assumption would be that it lacks a short circuit, e.g. "don't do anything if the new value and the old value are the same".
Then my second assumption would be that the control that is being bound to this property is setting it (after being bound). This can happen with list-type controls when SelectedItem is bound.
The resulting chain of events might be something like:
Code sets property
PropertyChanged event is fired
Binding sets the value on a control
Control reports it's value has been changed, and two-way binding sets the value on the ViewModel again
The lack of a short circuit causes the PropertyChanged event to be raised again
The binding sets the value on the control again (to the same value as before)
The control does not report a change, because it's property is short-circuited properly
My guess is that if you were to short circuit your setter (by checking against the existing value and bailing out if they are the same) this behavior would stop.
On a build server, I see some weird message. It doesn't say so, but I think it's from some software called 'fx cop'
Warning CS0067: The event 'SunGard.Adaptiv.AnalyticsEngine.UI.CommonControls.DisabledCommand.CanExecuteChanged' is never used
How can I silence this message? Without changing what my class does.
sealed class DisabledCommand : ICommand
{
public event EventHandler CanExecuteChanged;
I stumbled upon docs for System.Diagnostics.CodeAnalysis.SuppressMessageAttribute which sounds useful, but there aren't any examples for my warning.
If you need to create an event that is never raised, you should make a noop event:
public EventHandler CanExecuteChanged {
add { }
remove { }
}
The compiler is complaining because a default ("field-like") event will create a hidden backing field to store the handlers. Since you never raise the event, that field just wastes memory.
I have a custom user control extending the Listbox class. Inside of it I am overriding OnSelectionChanged to add/remove Adorners to any selected/unselected items. This all works when I select an item using the mouse, but when I programmatically add items to the listbox using
myListBox.SelectedItems.Add(newItem) // newItem is already a member of myListBox.Items
It does not execute the OnSelectionChanged code.
Update: Unless I'm crazy (which is always possible) it seems there is a difference in behaviour between calling this from the parent object
myListBox.SelectedItems.Add(newItem)
and this method inside my extended listbox class
Public Sub AddSelectedItem(newItem as Object)
Me.SelectedItems.Add(newItem)
End Sub
For some reason the second option is triggering the event while the first one isn't.
you need to add this line of code first
myListBox.Items.Add(newItem)
The solution here is that calling SelectedItems.Add() from inside an extension of ListBox
public class MyListBox : ListBox
{
public void AddSelectedItems(object newSelectedItem)
{
// works
this.SelectedItems.Add(newSelectedItem);
}
}
will trigger the OnSelectionChanged event.
Calling it like this from the window will not trigger the event
private sub SomeWindowMethod()
{
// does not work
this.MyListBoxInstance.SelectedItems.Add(newSelectedItem);
}
So, I'm having troubles implementing a separate thread. This is because I have a simple class, and in it I start a new thread. So, as it is not any form, I haven't found any way to make it call the function in the UI Thread.
So, I cannot use the Invoke method. Is there any way to call a function from another thread?
I am going to assume that you have events exposed from your class and that you want the event handlers to execute on a UI thread. I suppose you could have a callback that the caller specifies as well. Either way the pattern I will describe below will work in both cases
One way to make this happen is to have your class accept an ISynchronizeInvoke instance. Form and Control instances implement this interface so a reference to one of them could be used. You could make it a convention that if the an instance is not specified then event handlers executed by raising events on your class would execute in the worker thread instead of the thread hosting the ISynchronizeInvoke instance (usually a form or control).
Public Class YourClass
Private m_SynchronizingObject As ISynchronizeInvoke = Nothing
Public Sub New(ByVal synchronizingObject As ISynchronizeInvoke)
m_SynchronizingObject = synchronizingObject
End Sub
Public Property SynchronizingObject As ISynchronizeInvoke
Get
Return m_SynchronizingObject
End Get
Set(ByVal value As ISynchronizeInvoke)
m_SynchronizingObject = value
End Set
End Property
Private Sub SomeMethodExecutingOnWorkerThread()
RaiseSomeEvent()
End
Private Sub RaiseSomeEvent()
If Not SychronizingObject Is Nothing AndAlso SynchronizingObject.InvokeRequired Then
SynchronizingObject.Invoke(New MethodInvoker(AddressOf RaiseSomeEvent)
End If
RaiseEvent SomeEvent
End Sub
End Class
The first thing to notice is that you do not have to specify a synchronizing object. That means you do not have to have a Form or Control reference. If one is not specified then SomeEvent will be raised on the worker thread. This is the same pattern that is used in the System.Timers.Timer class.
Try to expose some events in your class, fire them when you need to notify your UI and finally make your UI Component register to these events,
when the event is fired, the listener methods will be executed. there you can use Control.Invoke or Control.BeginInvoke to execute your code on the UI thread.