C# How to unsubscribe click for BaloonToolTip - c#

I'm writing an application that shows notifications trough baloontips over notifyicon. There are two kinds of notifications I want to display - normal baloontip and clickable baloontip. I want clickable baloontips to open some url in web browser. The problem is that events stacks over baloontip.
I'm not sure if this explanation says anything, so here's an example:
code:
NotifyIcon ni = new NotifyIcon();
void showClickableNotification(string title, string content, string url)
{
ni.BaloonTipClicked += new EventHandler((sender, e) => ni_BalloonTipClicked(sender, e, url));
ni.ShowBaloonTip(1, title, content, ToolTipIcon.Info);
}
void ni_BalooTipClicked(object sender, EventArgs e, string url)
{
Process.Start(url);
}
every use of showClickableNotification will assign one more url to BallonTipClicked event
I want to clear event after notification will hide, to prevent opening multiple tabs unassociated with current notification.
Also, when normal notification is shown after a clickable one it's click opens all the stacked urls as well.
I tried to assign an empty function for ni.BaloonTipClicked += emptyFunction this, but += operator just adds another event to the pool instead of overwriting it. -= does not work since I'm adding new event every time. I guess I could do some global variable that holds current url and avoid assigning new everytime (-= would work then), but it looks like cheap workaround. Is there any (correct?) way to do it?

Related

Create a void method for each button

Hi im hoping someone can assist im still new to programming and this is a noob question but i have created a Visual studio - C# (Windows Form Application) and now the question reads to Create a void method for each of my buttons i created in the form and telling me even what to name the method.
but on my research The void keyword is used in method signatures to declare a method that does not return a value.
LinkToAddresses () will be my void method for address the (button), so my question is do i just put in this void method and its going to do nothing?
im just going to link the full question maybe im just really not understanding this>?
''
The below form will represent the main form from which the user will navigate to the other forms. Meaning each button should be linked to the appropriate form. E.g. If button Manage Addresses is clicked the form managed addresses should be displayed. The Exit button should successfully terminate the program.
Create a void method for each button and name them as follow: LinkToAddresses (), LinkToCustomers (), LinkToDrivers (), LinkToStatus (), and LinkToFreight (). The methods should be called under the appropriate button. For the exit button create a void method named AppExit () this should terminate the program.
''
I would appreciate any help or guidance, thank you in advance.
Visual studio usually handles the button actions easily. Just place the buttons on your form, then rename the buttons to LinkToAddresses, LinkToCustomers, LinkToDrivers, LinkToStatus, LinkToFreight and AppExit. Then simply just double click on the each button and visual studio will create a void method for their click event.
using System;
using System.Windows.Forms;
namespace YourApp
{
public partial class FormMain : Form
{
private FormManagedAddresses formManagedAddresses = null;
public FormMain()
{
InitializeComponent();
}
private void LinkToAddresses_Click(object sender, EventArgs e)
{
if (formManagedAddresses != null)
{
formManagedAddresses.Close();
}
formManagedAddresses = new FormNews();
formManagedAddresses.Show();
}
private void AppExit_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}
The closest thing to a buttons function, is the Click Event Handler. While specific names vary based on Display technology (WinForms, WPF/UWP, ASP.Net), that is the general pattern for Graphical User Interfaces. It is called event driven programming. Even things that have a different programm flow like Games and Web Applications usually try to imitate it.
The signature of a event is given during its definition and must be strictly followed. Usually void NameOfTheEvent(object sender, SampleEventArgs e).
A return type of void is extremely common with events. If there is to be any output, that usually is handeled via a property in the Event Args or by directly doing stuff with the other GUI Elements.
If you want a button to do nothing, you just never give it a event handler. Every single button you ever used, was given a implicit or explicit event handler to do exactly what it did. If you want it to conditionally do nothing, either disable the Button so it can not be clicked, or put a proper if-statement into the event Handler.
A advanced topic would be the command pattern, where there is a bunch of commands in code behind. And each button, menu item and key combination is meerely a way to trigger said command - a representation for hte user to call the command.
You can share a single event across any number of Elements. AS you can see above, the pattern for events includes object sender as argument. This means you can check if it is a specific Button instance that called the event. Or even "unpack" the specific button, do look at stuff like Display String, Tag to get data from it. However, as a general rule retrieving data from the GUI is a bit frowned - ideally the GUI should only represent the data in the backend.

Use asynchrony with GeckoFX web browser

I have a problem, I am trying to work with a custom webbrowser for a specific website.
The problem I am having with GeckoFX is that some times I need to wait for DocumentCompleted to continue with execution of particular methods.
I don't want to put all my code into one large DocumentCompleted event, as that seems silly and wrong.
I got the code to work by using the Application.DoEvents() as follows, but I read that this is not a right way to go, and that webbrowser should be best run as async.
private void AddNewTab(string tmsAddress) //add a new browser to my form
{
TabPage tab = new TabPage();
browserTabControl.TabPages.Insert(browserTabControl.TabCount - 1, tab);
GeckoWebBrowser browser = new GeckoWebBrowser();
tab.Controls.Add(browser);
tmsBrowser.Dock = DockStyle.Fill;
tmsBrowser.Navigate(address);
tmsBrowser.DocumentCompleted += new EventHandler<Gecko.Events.GeckoDocumentCompletedEventArgs>(tmsBrowser_DocumentCompleted);
}
Navigation on the page is manual, i.e. users work with the page normally, but from time to time they can use a shortcut button to get somewhere.
private void someButton_MouseUp(object sender, MouseEventArgs e)
{
GeckoWebBrowser browser = getCurrentBrowser();
//get some data from the page here
OpenPageInContentFrame(address + parameter1 + parameter2); //I need to wait for this page to load and then do HighlightItemRow()
while (!eventHandled) //documentCompleted events sets the bool as 'true'
{
Application.DoEvents();
}
HighlightItemRow(browser, parameter1);
}
}
I wanted to go with ManualResetEvents instead of while() and Application.DoEvents(), but using manResEvent.WaitOne() causes the whole application to freeze, including the navigation, so the page never actually loads. I think this must be because it's all in a single thread, I don't know how to make it working - I never used anything async etc.

Multiple frames of the same type Windows 8 c#

I have an application for Windows 8 with a page (Frame) for displaying a list of items and a page for downloading & displaying the items details. I am also using MVVM Light for sending notifications.
Application use goes something like this:
Open Main Page
Navigate to List Page
Frame.Navigate(typeof(MyPage));
Choose Item
//Complete logic
Frame.GoBack();
Back on Main Page, I start downloading the file in the view model, I send ONE NotificationMessage saying BeginDownloadFile and after it is downloaded ONE NotificationMessage saying EndDownloadFile.
The first time I do steps 2,3, & 4 my NotificationReceived method is hit once, the second twice and so forth.
private async void NotificationMessageReceived(NotificationMessage msg)
{
if (msg.Notification == Notifications.BeginDownloadFile)
{
FileDownloadPopup.IsOpen = true;
}
else if (msg.Notification == Notifications.EndDownloadFile)
{
FileDownloadPopup.IsOpen = false;
}
}
Additional information: I only have one FileDownloadPopup, yet each time, an additional popup is shown each time the NotificationMessageReceived method is called.
My only conclusion is that between navigating forwards and backwards in my app, there are multiple MainPages being created and never closed. This results in many NotificationsMessageReceived methods just waiting for a notification to come their way so they can show their popup.
I have two questions:
1. Does this sound like normal behaviour for a Windows 8 app?
2. How can I close all instances of the MainPage or return to the previous instance without creating a new instance?
Please let me know if I have missed something important out before marking my question down.
This sounds normal to me. The default navigation behaviour in Windows 8 is to create a new page instance each time you navigate to a new page, regardless of whether this is forward or back navigation.
Try setting the NavigatinCacheMode on MainPage to Required. See the MSDN documentation for details of how page caching works.
It sounds like you are registering eventhandlers in the page and then not removing them. Each time you navigate to the page again the handler is being added again in addition to the one you previously added. Try to add your event handler in OnNavigatedTo, and make sure you unregister it in OnNavigatedFrom.
protected override void OnNavigatedTo(Windows.UI.Xaml.Navigation.NavigationEventArgs e)
{
MyEvent.OnDownloadRequest += MyLocalDOwnloadHandler; // add the handler
}
protected override void OnNavigatedFrom(Windows.UI.Xaml.Navigation.NavigationEventArgs e)
{
MyEvent.OnDownloadRequest -= MyLocalDOwnloadHandler; // remove the handler
}

C# Webbrowser Control: Navigating to a List to URLs

I am working on a web crawler. I am using the Webbrowser control for this purpose. I have got the list of urls stored in database and I want to traverse all those URLs one by one and parse the HTML.
I used the following logic
foreach (string href in hrefs)
{
webBrowser1.Url = new Uri(href);
webBrowser1.Navigate(href);
}
I want to do some work in the "webBrowser1_DocumentCompleted" event once the page is loaded completely. But the "webBrowser1_DocumentCompleted" does not get the control as I am using the loop here. It only get the control when the last url in "hrefs" is navigated and the control exits the loop.
Whats the best way to handle such problem?
Store the list somewhere in your state, as well as the index of where you've got to. Then in the DocumentCompleted event, parse the HTML and then navigate to the next page.
(Personally I wouldn't use the WebBrowser control for web crawling... I know it means it'll handle the JavaScript for you, but it'll be a lot harder to parallelize nicely than using multiple WebRequest or WebClient objects.)
First of all, you are setting new url to same web browser control, even before it has loaded anything, this way you will simply see the last url on your browser. Definately browser will certainly take some time to load url, so I guess navigation is cancelled well in advance before Document_Completed can be fired.
There is only one way to do this simultaneously,
You have to use a tab control, and open a new tab item for every url and each tab item will have its own web browser control and you can set its url.
foreach(string href in hrefs){
TabItem item = new TabItem();
WebBrowser wb = new WebBrowser();
wb.DocumentCompleted += wb_DocumentCompleted;
wb.Url = href;
item.Child = web;
tabControl1.Items.Add(item);
}
private void wb_DocumentCompleted(object sender, EventArgs e){
/// do your stuff...
}
In order to improve above method, you should see how can you create multiple tab items in different UI threads, its pretty log topic to discuss here, but it is still possible.
Another method is to do use a queue...
private static Queue<string> queue = new ...
foreach(string href in hrefs){
queue.Enqueue(href);
}
private void webBrowser1_DocumentCompleted(object sender, EventArgs e){
if(queue.Count>0){
webBrowser1.Url = queue.Dequeue();
}
}

c# / WPF : Make a Browse for File Dialog

I'm new to WPF and am trying to make my first WPF desktop application using VC# Express.
I'm trying to get make three open file dialogs complete with text fields that show the specified path if the user chooses a file. I found working code to make the dialog box appear at the click of a button, but how do I get a text field to update/bind to the file path?
Something similar to how the file input boxes in HTML work would be ideal.
...
EDIT:
Okay I read the post just below mine and found the solution...
Now, how about redirecting console output to a text field?
To answer your question about redirecting console output:
You'll be better off changing the code to fire an event with the string you wish to output. Then in the UI add a handler for that event and in the handler update the text field.
To declare an event add something like this code in your processing class:
public event EventHandler<StringEventArgs> Process_Message;
where StringEventArgs is a class based on EventArgs that wraps the message for sending.
To fire the event add something like this code in your processing class:
Process_Message(this, new StringEventArgs(message));
To attach a message handler in your UI class:
process.Process_Message += Process_Message;
To handle the event add something like this code to your UI class:
private void Process_Message(object sender, StringEventArgs e)
{
Action action = () => UpdateStatus(e.Message);
{
Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, action);
}
else
{
action();
}
}
You need to do the threading test as the UI can't be updated from a different thread.
Then the UpdateStatus method:
private void UpdateStatus(string message)
{
statusTextBox.Text = message;
}
Obviously you'll need to rename things to be appropriate to your application.
Look up events and EventArgs in the MSDN.
If i understand you correctly
Use the FileDialog.FileName to the the Full path .. and bind that to your text box.
76mel

Categories

Resources