Get label in a static method inside class c# - c#

I know there are many similar questions but I am kind of restricted in many terms for this case. I am using SharpBox to upload files to Dropbox and in order to create a progress bar visible to user, I am using a static method where SharpBox returns the percenatge. It is all fine but I need to return this information to the aspx page or javascript somehow.
I cannot add a parameter to the method. I could remove the static from the method however it does still gives an exception null on the label which is quite strange (probably because the method fires from SharpBox dynamically).
So the method UploadDownloadProgress is the part where I have problems with.
public class docUpload
{
static public void Doc_Upload()
{
dropBoxStorage.UploadFile(stream, filename, entry, UploadDownloadProgress);
}
static void UploadDownloadProgress(Object sender, FileDataTransferEventArgs e)
{
// I need the e.PercentageProgress on aspx page
System.Diagnostics.Debug.WriteLine(e.PercentageProgress);
// This wont work since it is a static method
myLabel.Text = e.PercentageProgress.ToString();
e.Cancel = false;
}
}
I need the e.PercentageProgress in the label. I also alternatively tried to call javascript without success. Could you suggest any other alternatives?

Try something like this:
public class docUpload
{
static public void Doc_Upload()
{
dropBoxStorage.UploadFile(stream, filename, entry, ProgressInformer.UploadDownloadProgress);
}
}
public class ProgressInformer {
public static string Progress = "0";
static void UploadDownloadProgress(Object sender, FileDataTransferEventArgs e)
{
// print a dot
System.Diagnostics.Debug.WriteLine(e.PercentageProgress);
// Need to show this on a label or return to front end somehow
ProgressInformer.Progress = e.PercentageProgress.ToString();
e.Cancel = false;
}
}
Now since you are setting the static variable with value you can access it from somewhere else. Then you can use that value to echo on the front-end using some method or service. Possibly like this:
public string EchoToFrontEnd()
{
return ProgressInformer.Progress;
}
Limitation: If this works for you still this solution is not thread safe. That means, you cannot echo progress for multiple downloads. You'll have to work with a single download at a time.
Hope this helps...!

Related

c# Difference in behavior when call to method is uncommented in comparison to uncommenting everything in called method

I have an Application that uses Selenium Browser extension for chrome.
As this extension does not close the chrome browser on process exit I implemented the following code into my application:
static void OnProcessExit(object sender, EventArgs e)
{
API.Quit();
}
class API
{
public static IWebDriver browser = new ChromeDriver(Service(), Options());
public static void Quit()
{
if (!String.IsNullOrEmpty(browser.CurrentWindowHandle))
{
browser.Quit();
browser.Dispose();
}
}
}
Please note that both, OnProcessExit and Quit are in two separate classes, files and namespaces. I put them together here for easier code view.
there appears to be a bug that opens chrome when the driver is not currently open. Which is why I implemented the if case.
Now comes the weird thing:
Even when I uncomment everything within Quit(), the browser opens:
static void OnProcessExit(object sender, EventArgs e)
{
API.Quit();
}
class API
{
public static IWebDriver browser = new ChromeDriver(Service(), Options());
public static void Quit()
{
/*
if (!String.IsNullOrEmpty(browser.CurrentWindowHandle))
{
browser.Quit();
browser.Dispose();
}
*/
}
}
Whereas when I uncomment the call, the browser does not open:
static void OnProcessExit(object sender, EventArgs e)
{
//API.Quit();
}
class API
{
public static IWebDriver browser = new ChromeDriver(Service(), Options());
public static void Quit()
{
if (!String.IsNullOrEmpty(browser.CurrentWindowHandle))
{
browser.Quit();
browser.Dispose();
}
}
}
My Question: Why is it that my application behaves differently wether I uncomment the call or everything in Quit()?
I think it is because static constructor.
In your first example, your pseudo-code is like this:
Call API.browser = new ChromeDriver(Service(), Options());
Call API.Quit()
In your second example nothing happens, because you are not calling static class.
To further test, try creating this method inside API class:
public static void FakeInit() //use to invoke static class constructor.
{
//leave it empty.
}
And then call it instead of Quit:
API.FakeInit();
And you will see browser is initialized but not closed. It seems magical, but this call is actually doing this:
Call API.browser = new ChromeDriver(Service(), Options());
Call API.FakeInit() which is empty
PS
Main recomendation - do not use static if you are not working with extensions or marshal some unmanaged code. Just use it like this:
new API().Quit();
It is perfectly normal, you can create it at startup, pass it inside other classes, close and dispose it whenever you feel like it. And this way you will be full aware of what is going on, and why your browser is opening in some unpredicted place just because you invoked some helper method from static class. Though, I often use static for extension methods (to create DSL), I highly dislike it when using this as singleton.

Creating a dll but need to reference a changeable function/ void/ code

So I am creating a dll and what it does is it basically authenticates a username and password with a server and if it wrong it writes failure in an output box and if it is correct it launches another form or does whatever the person who is using the dll wants it to do. Here is the code:
using (StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
LaunchCode.Globals.output = "SUCCESS" + Environment.NewLine;
//Success action
json = streamReader.ReadToEnd(); //---Can't get the nested JSON, read the entire response minus the 200 code.
}
Where I have "//Success action" is where the code would go for whatever the user wants the dll to do (open a form, open a message box, etc) but this being a dll the user doesn't have access to the code. So I wanted to have the dll reference a void or what ever would work, in a different form. I tried looking for example on how to do this on google but I couldn't really find anything and I really have no idea on how to accomplish this.
If you need me to clarify anything just ask and Thanks for the help in advance.
You need to use delegates. Below is an example code that uses a special delegate Action. You can use either inbuilt delegates or make your own.
public class Program
{
public void Main(string[] args)
{
Foo foo = new Foo();
foo.SomeMethod(ActionProvider.ShowMessageBox);
}
}
public static class ActionProvider
{
public static void ShowMessageBox()
{
//Write code for showing message box
Console.WriteLine("Showing message box");
}
}
// Assume this class to be in another dll
public class Foo
{
public void SomeMethod(Action callback)
{
//Do something
callback();
//Do something else
}
}

Method not returning a value

I have a method that should return the domain name of the current user in a label.text. I call the method in the load event of the form but nothing comes up, no errors in the code either. Maybe im starting the object wrong? It works if i put the method code in the load event directly.
public partial class Main Form
{
public Main()
{
InitializeComponent();
}
public string getCurrentDomain()
{
return domainNameValue.Text = Environment.UserDomainName;
}
public void Main_Load(object sender, EventArgs e)
{
Main main = new Main();
main.getCurrentDomain();
}
}
I think your problem is in the Main_Load function you are creating a new form instead of changing the current form, The correct code is:
public void Main_Load(object sender, EventArgs e)
{
this.getCurrentDomain();
}
Or if you wnat to have another form just show it using main.show()
The problem is because you are creating new instance of Main class in your Main_Load method. So, the method getCurrentDomain() change label text of the instance that you are creating not the label in the form where Main_Load is executed.
Also the body of method getCurrentDomain() violates the Principle of least astonishment because that method is generating side effect which changes text of a label. But the name of method suggest only that the current domain name is being returned.
You could use
public string getCurrentDomain() // Method: Get current domain
{
domainNameValue.Text = Environment.UserDomainName;
return Environment.UserDomainName;
}

A cleaner way to automatically call one method after another?

Is it possible to design a method in such a fashion, that it knows it must automatically call a next method in succession upon exiting?
In the following example, I must call Refresh() to cause my form to repaint after this event takes place. The problem is that, it's ugly to call Refresh() after, for example, 20 different events which must make the form refresh. e.g
private void PriorityLine_Click(object sender, EventArgs e)
{
_showPriorityLine = (_showPriorityLine) ? false : true;
Refresh(); // Must call refresh for changes to take effect.
}
I suppose what I'm looking for is some kind of signature I can apply to the method to cause it to automatically chain to the next method, regardless from where its called. e.g
(I know this isn't syntactically correct.)
private void PriorityLine_Click(object sender, EventArgs e).Refresh()
{
_showPriorityLine = (_showPriorityLine) ? false : true;
}
I want to seperate the interface of the method, from the logic contained within the method. I understand it would be the exact amount of effort, if not more. For example, if I were to edit the method and accidently removed Refresh, it would cause my application to break. Whereas, if the Refresh method was outside of the actual logic of the method, I could do anything within the method without worrying about removing the next chain of logic.
Sounds like what you want is Aspect Oriented Programming, there are a number of different frameworks to enable you to have stuff "magically" happen after some set of methods have run, have a look here AOP programming in .Net?
I'm not aware of any really clean way. One method would be to use PostSharp.
You could encapsulate the changes which would cause the form to refresh into form-level properties.
For instance,
private bool _showPriorityLine;
private bool ShowPriorityLine
{
get { return _showPriorityLine; }
set
{
_showPriorityLine = value;
Refresh();
}
}
Then your event would just be
private void PriorityLine_Click(object sender, EventArgs e)
{
ShowPriorityLine = !ShowPriorityLine;
}
Of course, that only cleans up your code if you have several events manipulating the same variables that cause the form to need refreshing.
Taking into consideration your particular problem and the solutions posted, I would say the "cleanest" approach here would be to implement a Property Changed Notification just for internal use in the form i.e. you don't need to expose the event like in the MSDN example.
This way you could maintain an internal list of properties that you know will require the form to be refreshed e.g.
private List<string> _refreshProps = new List<string>();
private bool _showPriority;
public void Form()
{
_refreshProps.Add("ShowPriority");
... etc
}
// only implement properties like this that need some extra work done
public bool ShowPriority
{
get { return _showPriority; }
set
{
if (_showPriority != value)
{
_showPriority = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("ShowPriority");
}
}
}
// basic property that doesn't require anything extra
public bool AnotherProperty { get; set; }
public void Refresh()
{
// refresh the form
}
protected void OnPropertyChanged(string name)
{
if (_refreshProps.Contains(name))
Refresh();
}
The benefit of this approach is if in the future you needed to do other "stuff" after particular properties you can simply introduce another list and handle it again in your OnPropertyChanged method.
Don't call Refresh, call Invalidate. The mechanism you need is already built into Windows. Calling Invalidate simply makes a note that the window needs repainting. The operating system will eventually post a WM_PAINT message (typically after the root DispatchMessage call finishes, but the exact implementation is irrelevant).
Use a property that calls Refresh in the setter.
Something like this:
private void RefreshAfter(Action action)
{
action();
Refresh();
}
UPDATED TO MAKE IT MORE OBVIOUS:
private void DoSomeUiShiznit(Action action)
{
action();
// other parts of the code don't realize that Refresh has to be called.
// But that's cool. I got it covered.
Refresh();
}
private void PriorityLine_Click(object sender, EventArgs e)
{
DoSomeUiShiznit(() => { _showPriorityLine = !_showPriorityLine; });
}
UPDATE -- Just a message to the down-voters:
What some of you are too blind to see is that this is not all that different from:
[SomeRefreshAttribute]
private void PriorityLine_Click(object sender, EventArgs e)
{
_showPriorityLine = !_showPriorityLine;
}
Except that it is simpler, and doesn't require adding another framework to the solution. And yet the other answer suggesting as much don't get down-voted!
What's wrong with you people?

Use class method from another class

I am trying to use a method inside class, from another class.
namespace Crystal.Utilities
{
public class Logging
{
public static void Log()
{
//dostuff
Crystal.MainForm.general_log_add_item("Hello World");
}
}
}
namespace Crystal
{
public partial class MainForm : Form
{
public void general_log_add_item(string msg)
{
listBox1.Items.Add(msg);
}
}
}
I want to be able to call Crystal.Utilities.Logging.Log() from anywhere, and that to be able to call Crystal.MainForm.general_log_add_item() . But It doesn't let me, because if I put it as public, then I can't see it, if it's static then It can't interact with my listbox.
This is a wrong approach. Your class should not call into the UI, as the UI could change. The class should not know nor care about the UI. Instead, the class could expose an event that the form could subscribe to, and update based upon the information contained within the event's arguments.
Here's a hastily thrown together example.
class Program
{
static void Main()
{
Logger.OnLogging += Logger_OnLogging;
Logger.Log();
Logger.OnLogging -= Logger_OnLogging;
}
static void Logger_OnLogging(LoggingEventArgs e)
{
Trace.WriteLine(e.Message);
}
}
public class Logger
{
public delegate void LoggingEventHandler(LoggingEventArgs e);
public static event LoggingEventHandler OnLogging;
public static void Log()
{
// do stuff
RaiseLoggingEvent("Data logged");
}
protected static void RaiseLoggingEvent(string message)
{
if (OnLogging != null)
OnLogging(new LoggingEventArgs(message));
}
}
public class LoggingEventArgs : EventArgs
{
public LoggingEventArgs(string message)
{
this.Message = message;
}
public string Message { get; private set; }
}
Instead of implementing it as a static method, try implementing as a singleton. It's a common trick to make an instance global in scope, and restrict to one instance, without making everything static (and thus unable to be used as an instance).
You have to understand that the window is not static, there is one instance of him, thats why the method cant be static,
you can use
Application.Windows to reach this instance and call the add method.
or you can register the window in his constructor on another class that will mediate the Logging and the window.
If you don't understand tell me and I'll try to be more clear
When you declare a method as "static" you're saying that it's not dependent upon a specific instance of the class it's in.
For example if you have a class named "chair" and you want to count how many chairs there are, you'll do that with a static field, and a static method to return that field's value.
The count of all chairs is not related to a specific chair.
In your case you want to add a static method to add an item to a specific instance of a Form. That's impossible and doesn't make sense.
If you want to add an item to a listBox, it must be through a public method.
So basically what I'm saying is - rethink what you're trying to do, there's a good explanation as to why you're not succeeding in doing that.

Categories