Mono GTK# - PropertyNotifyEvent of window or widget - events

I want to be able to react if a property of a given window or widget has been changed and found the Gtk.Widget.PropertyNotifyEvent event. The (mono) documentation says that it will be fired if any property has been changed. So I've tried to make use of it but my event handler method is never invoked:
protected void DoSomething()
{
Gtk.Window __Window = new Gtk.Window(Gtk.WindowType.Toplevel);
Gtk.Button __Button = new Gtk.Button();
__Window.Add(__Button);
__Button.PropertyNotifyEvent += this.ButtonPropertyChangedEventHandler;
... // Show the window
__Button.Label = Mono.Unix.Catalog.GetString("This is a test button");
}
protected void ButtonPropertyChangedEventHandler(object o, PropertyNotifyEventArgs e)
{
// Handle the event
}
Do I miss something? Or did I understand something very basic wrong? Or is there another approach to achieve my goal?

Property change notifications need to be explicitly enabled by setting the GDK_PROPERTY_CHANGE_MASK flag, as explained here:
https://developer.gnome.org/gtk3/stable/GtkWidget.html#GtkWidget-property-notify-event
In Gtk# you just need to add the following line to your code:
__Button.Events |= Gdk.EventMask.PropertyChangeMask;
And the handler assigned to the PropertyNotifyEvent event will start to receive property change notifications. Gtk# enables some events implicitly but all others should be enabled from user code or from the stetic designer.

Related

Outlook VSTO Handling SelectionChange correctly (currently doubleclick crashes Addin)

From what I understand you need to track Activation and Deactivation of the Explorers. During activation, you need to add SelectionChange event handlers for the current explorer.
This seems to work perfectly for single clicks on AppointmentItems. But it crashes the Addin when double-clicking on an appointment series and selecting a single Appointment.
Here is the source:
On class level
private Outlook.Explorer currentExplorer = null;
private Outlook.AppointmentItem currentAppointmentItem = null;
within Startup:
currentExplorer = this.Application.ActiveExplorer();
((Outlook.ExplorerEvents_10_Event)currentExplorer).Activate +=
new Outlook.ExplorerEvents_10_ActivateEventHandler(
Explorer_Activate);
currentExplorer.Deactivate += new
Outlook.ExplorerEvents_10_DeactivateEventHandler(
Explorer_Deactivate);
The event handlers:
void Explorer_Activate()
{
currentExplorer.SelectionChange += new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(Selection_Change);
}
void Explorer_Deactivate()
{
currentExplorer.SelectionChange -= new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(Selection_Change); ;
}
private void Close_Explorer()
{
}
private void Selection_Change()
{
Outlook.MAPIFolder selectedFolder = currentExplorer.CurrentFolder;
if (currentExplorer.Selection.Count > 0)
{
Object selObject = currentExplorer.Selection[1];
if (selObject is Outlook.AppointmentItem)
{
currentAppointmentItem = (Outlook.AppointmentItem)selObject;
}
else
{
currentAppointmentItem = null;
}
}
}
What am I overlooking? Is the form of deregistering a problem?
Try to add try/catch blocks to the event handlers. The Outlook object model can give you unpredictable results sometimes. It is worth adding them and find where an exception is thrown.
currentExplorer.Selection.Count
Also, you may subscribe to the SelectionChange event in the NewExplorer event and don't switch between explorers when they are activated or deactivated. The event is fired whenever a new explorer window is opened, either as a result of user action or through program code.
The only thing which I added was a handler for NewInspector and InspectorClose events along with Marshal.ReleaseComObject(). The only thing which I can imagine that double clicking while debugging I got in some kind of race condition (because double clicking also triggers the Selection_Change event). But this is only a guess.
You do not need to add and remove event handlers as an explorer is activated / deactivated. Are you trying to support multiple explorers? In that case, create a wrapper class that hold the Explorer object as it member and uses its methods as event handlers.

Xamarin Forms Map Viewable Area event handler

I have a Xamarin form map on my screen and I'm using PropertyChanged event to retrieve geolocation information from my server and display the proper pins on screen.
While coding the solution I noticed the PropertyChanged event is triggered multiple times (up to 10 times) with a single zoom or drag action on the map. This causes unnecessary calls to server which I want to avoid.
Ideally I want to make only one call to server when the final PropertyChanged event is called but I cant's find an easy solution to implement this.
At this point I've added a refresh button to my page that becomes enabled when a PropertyChanged event happens and I disable it after user uses the button.
Obviously this fixed the too many calls to server but made the solution manual.
I was wondering if there is a more elegant way to make the server call but do it automatically.
Thanks in advance.
I just test the PropertyChanged event on iOS side and it just triggered one time with a single zoom or drag action on the map.
While if it really triggered multiple times, you can use a timer to call the server when the final PropertyChanged event is called, for example:
public partial class MapPage : ContentPage
{
Timer aTimer;
public MapPage()
{
InitializeComponent();
customMap.PropertyChanged += CustomMap_PropertyChanged;
}
private void CustomMap_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (aTimer != null)
{
aTimer.Enabled = false;
aTimer.Stop();
aTimer.Close();
}
aTimer = new Timer();
aTimer.Interval = 1000;
aTimer.Enabled = true;
aTimer.Elapsed += ATimer_Elapsed;
aTimer.Start();
}
private void ATimer_Elapsed(object sender, ElapsedEventArgs e)
{
aTimer.Stop();
//do web request
Console.WriteLine(sender);
Console.WriteLine("CustomMap_PropertyChanged");
}
}
In the above code, I set the Interval = 1 second, that means in 1 second, whatever how many times PropertyChanged triggered, only the last call will trigger the ATimer_Elapsed function.
The Interval can be set to any value depending on your requirement.

rxBindings - How to know what consumer type should be when debouncing click events?

using rxBindings im trying to slow down a click event but i would like to know what the parameter is need.
For example, here is a call i am doing on a imageview. So ImageView v;
RxView.clicks(v)
.throttleFirst(400, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
.subscribe(new Consumer<Object>() {
#Override
public void accept(#io.reactivex.annotations.NonNull Object v) throws Exception {
showBottomSheet(getAdapterPosition());
}
});
but im im not sure what the parameter in accept should be ?
I was expecting i would get the view here but when i try changing the type to View i get an error of no such method.
If you look at the source code of the Observable generate using RxView.clicks(), you will see that when the click happens, the following code is triggered:
observer.onNext(Notification.INSTANCE);
that is defined in the library, as:
public enum Notification {
INSTANCE
}
It is just a convenient way for indicating that the event happened, it doesn't carry any extra information.

ViewChanged suppress on Windows Phone 8.1

There is a way to fire the event ViewChanged (that was present in previous WP8) within an Windows Phone 8.1 app? I use Windows.UI.Xaml.Controls.Maps and I will manage the map when the view animation finishes.
You can try to use on of these events of the MapControl class:
ManipulationStarted: http://msdn.microsoft.com/en-us/library/hh702372.aspx
CenterChanged: http://msdn.microsoft.com/en-us/library/windows.ui.xaml.controls.maps.mapcontrol.centerchanged.aspx
ZoomLevelChanged: http://msdn.microsoft.com/en-us/library/windows.ui.xaml.controls.maps.mapcontrol.zoomlevelchanged.aspx
But the best event would be ManipulationCompleted: http://msdn.microsoft.com/en-us/library/windows.ui.xaml.uielement.manipulationcompleted.aspx
I've found that the LoadingStatusChanged event does what you want, provided you check the LoadingStatus first.
mapControl.LoadingStatusChanged += MapLoadingStatusChanged;
private void MapLoadingStatusChanged(MapControl sender, object args)
{
if (sender.LoadingStatus == MapLoadingStatus.Loaded)
{
// code here will only get hit when the map finishes drawing after a pan/zoom
}
}

How do I detect NSDatePicker ValueChanged in MonoMac?

Unlike UIDatePicker in Monotouch, the NSDatePicker in MonoMac does not appear to have "ValueChanged". How do I detect changes?
Ideally where datePicker is an NSDatePicker, I want to
datePicker.ValueChanged += DatePickerOnValueChanged
For events, I see "Activated" and "ValidateProposedValue", could it be the latter that I want?
Update. I think I can do something like below. Is it equivalent?
datePicker.Action = new MonoMac.ObjCRuntime.Selector ("datePickerAction:");
and
[Export("datePickerAction:")]
private void datePickerAction()
{
// stuff
}
In your ideal case, you say you want to use an event. The ValidateProposedValue event is fine for this:
picker.ValidateProposedDateValue += (object sender, NSDatePickerValidatorEventArgs e) => {
Console.WriteLine(e.ProposedDateValue);
};
It seems to correspond to the NSDatePickerCellDelegate method datePickerCell:validateProposedDateValue:timeInterval:, which is what I would use in Objective C.

Resources