I have 1 web form and multiple user controls. One of the user controls fires an event. The page is listening and gets the value the control sends out. However the other user controls listening attach to the event but never get to the method.
User Control 1
public delegate void GetOrgIdEventHandler(long orgId);
public event GetOrgIdEventHandler GetOrgId;
protected void gvSearchResults_SelectedIndexChanged(object sender, EventArgs e)
{
if (GetOrgId != null)
{
GetOrgId(Id);
}
}
Web Form
//Search1 is the Id of the User Control on the web form - This is working.
//It calls the method in the assignment
Search1.GetOrgId +=
new SearchGridViewSelectedIndexChangedEventHandler(GetTheOrgId);
User Control 2
//SearchUserControl is the name of the User Control 2 Class
protected SearchUserControl mySuc = new SearchUserControl();
//The line below works, however the method does not get called. This is where it fails.
//I set a breakpoint in GetTheOrgId but I never get to that break.
mySuc.GetOrgId += new SearchGridViewSelectedIndexChangedEventHandler(GetTheOrgId);
Yes, you can raise events in the first control, have it picked up in the parent, and then have the parent call a method/function in the second control. Example (in VB.Net):
User control one:
Partial Class user_controls_myControl
Inherits System.Web.UI.UserControl
Public Event DataChange As EventHandler
'now raise the event somewhere, for instance when the page loads:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
RaiseEvent DataChange(Me, New EventArgs)
end sub
end Class
This will raise an event, called DataChange, when the control loads. Or, you can raise it in response to another event withing the controls (like if a button gets pushed). This will raise an event that the parent can subscibe to, like this (assuming you have a control on the page called MyControl1):
Main Page:
Protected Sub myControl_dataChange(ByVal sender As Object, ByVal e As EventArgs) handles myControl1.DataChange
End Sub
Now, you can then expose a method in your second control, like this:
Partial Class user_controls_myOtherControl
Inherits System.Web.UI.UserControl
public sub callMe()
'do something
end Sub
end Class
You can then call the method in the second control, from the parent page, like this:
me.userConrol2.callMe()
If you still have questions, let me know.
Related
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.
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.
It is work only one time, than event handler not work.I do not understand why?
private void ThisAddIn_Startup(object sender, System.EventArgs e) {
var folder = Globals.ThisAddIn.Application.Session.DefaultStore.
GetDefaultFolder(Outlook.OlDefaultFolders.olFolderTasks);
foreach(Outlook.TaskItem item in folder.Items) {
item.BeforeDelete += BeforeDelete;
item.Save();
}
}
private void BeforeDelete(object item, ref bool cancel) {
MessageBox.Show("Удалено");
// Marshal.ReleaseComObject(item); must I do It?
}
The object that raises the event must be alive to raise the events. In you case you are setting an event sync on a local variable that gets garbage collected and hence does not raise the events anymore. Keep the object referenced on the global (class) level. It your case, it needs to be a list of TaskItem objects.
That being said, do not ever set event sinks on all items in a folder. You will kill Outlook. Since the user needs to select an item before attempting to delete it, process Explorer.SelectionChange event, clear the list of items, then set up event sinks on the items from the Explorer.Selection collection
I'm trying to using PhotoChooserTask for our purposes.
After calling photoChooserTask.Show() chooser is showed but when I choose a picture it's closing and event Completed not fired !
Why?
And more, after that PhotoChooserTask not showed next time when calling Show.
P.S. if i try this code in new solution - it will work fine, but why it doesn't work in our project?
PhotoChooserTask photoChooserTask;
private void button2_Click(object sender, System.Windows.RoutedEventArgs e)
{
photoChooserTask = new PhotoChooserTask();
photoChooserTask.Completed += new EventHandler<PhotoResult>(photoChooserTask_Completed);
photoChooserTask.Show();
// TODO: Add event handler implementation here.
}
void photoChooserTask_Completed(object sender, PhotoResult e)
{
//Bla bla bla
}
I solved this problem.
So, project CAN NOT have more than one photo chooser.
You can't declare PhotoChooserTask in Page1 and Page2 with different logic of processing.
Hope this will helpfull for someone.
You should make sure that you respect the guidelines for creating and initializing the object:
To ensure that your application receives the result of the
PhotoChooserTask, the object must be declared with class scope
within the PhoneApplicationPage class and you must call the chooser
constructor and assign the Completed event delegate within the page’s
constructor.
Source
I have a simple outlook ribbon with an editBox. Once the user clicks the send button, I capture the string in the editBox and use it in the Application_ItemSend..
My problem is, after the function is done, I want to RESET the UI of the ribbon (just the editBox) so that the user won't have the previously typed string in the same box when opening up a new message screen. I tried the Ribbon.Invalidate but I can't seem to get rid of that string value. When I re-open the "New Email" screen, the old value is still there.
Here is the code:
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load_2010">
<ribbon>
<tabs>
<tab idMso="TabNewMailMessage">
<group id="TaskManager" insertBeforeMso="GroupSend" label="Task Manager">
<editBox id="editboxTaskID" label="Task ID #: " onChange="editboxTaskID_OnChange"
imageMso="RecordsAddFromOutlook" sizeString="wwwwww"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
And the VB Code:
<Runtime.InteropServices.ComVisible(True)> _
Public Class CustomRibbon
Implements Office.IRibbonExtensibility
Private ribbon As Office.IRibbonUI
Public strTask_ID As String = ""
Public Sub New()
End Sub
Public Function GetCustomUI(ByVal ribbonID As String) As String Implements Office.IRibbonExtensibility.GetCustomUI
Return GetResourceText("Addin.Ribbon.xml")
End Function
Private Sub Application_ItemSend(ByVal Item As Object, ByRef Cancel As Boolean)
Me.ribbon.Invalidate()
Try
'SOME CODE HERE WHICH WORKS FINE!
Catch ex As Exception
End Try
End Sub
'Create callback methods here. For more information about adding callback methods, select the Ribbon XML item in Solution Explorer and then press F1.
Public Sub Ribbon_Load_2010(ByVal ribbonUI As Office.IRibbonUI)
Me.ribbon = ribbonUI
AddHandler Globals.ThisAddIn.Application.ItemSend, AddressOf Application_ItemSend
End Sub
Public Sub editboxTaskID_OnChange(ByVal control As Office.IRibbonControl, ByVal Text As String)
strTask_ID = Text
End Sub
Public Sub AttachmentRibonClick(ByVal control As Microsoft.Office.Core.IRibbonControl)
Globals.ThisAddIn.TriggerTaskWindow("Attachment")
End Sub
Private Shared Function GetResourceText(ByVal resourceName As String) As String
Dim asm As Reflection.Assembly = Reflection.Assembly.GetExecutingAssembly()
Dim resourceNames() As String = asm.GetManifestResourceNames()
For i As Integer = 0 To resourceNames.Length - 1
If String.Compare(resourceName, resourceNames(i), StringComparison.OrdinalIgnoreCase) = 0 Then
Using resourceReader As IO.StreamReader = New IO.StreamReader(asm.GetManifestResourceStream(resourceNames(i)))
If resourceReader IsNot Nothing Then
Return resourceReader.ReadToEnd()
End If
End Using
End If
Next
Return Nothing
End Function
End Class
The invalidate method is used to signal that a control has been updated and needs to be re-rendered on the screen. It will not clear data from a control. What you need to do is set the property on the control (the edit box in this case) that stores the offending string value to an empty string.
Ok, I figured it out.
Apparently after you invalidate the controls, you need to use GetText function of the Editbox to init the value.
Public Function editboxTaskID_GetText(ByVal control As Office.IRibbonControl) As String
Return ""
End Function
I also noticed other sites use different signature for the function - which does not work. I believe Microsoft changed this from a Sub to a Function when moving to 2010 Interop.
I wish Microsoft had better documentation for this.
Happy programming!