I wrote code about the settings page that uses static bool
then I need to Check If the public static bool changed or not In the form that I needed to call
(Form1 Is main form and Can be opened Once But Form2 Can open >1)
then I wrote this code
Form1:
private static bool Called = false;
public static bool HideButton
{
get { return Called; }
set
{
if (Called != value)
{
Called = value;
Update(); //function about updating buttons
}
}
}
Form2:
private void checkBox5_CheckedChanged(object sender, EventArgs e) {
if (checkBox5.Checked)
{
Form1.HideButton = true;
}
else
{
Form1.HideButton = false;
}
}
Then it said that you can't run non-static inside static
So I have an idea If I can check public static bool then call async void that is not static.
any idea?
Well, static means not instance, so you have one and only one Called value for all Form1 instances.
When you try to call Update() within static property set, the compiler complains: it doesn't know on which
instance should it be called (imagine, that there are three opened Form1).
You can either add some logic, e.g. let call Update on all opened Form1:
using System.Linq;
...
private static bool Called = false;
public static bool HideButton
{
get { return Called; }
set
{
if (Called != value)
{
Called = value;
// Assuming WinForms
// We call Update on all opened Form1 forms
foreach (var form in Application.OpenForms.OfType<Form1>())
form.Update();
}
}
}
Or you may let each Form1 instance have its own Called, i.e. drop static:
private bool Called = false;
public bool HideButton
{
get { return Called; }
set
{
if (Called != value)
{
Called = value;
Update();
}
}
}
Please, note, that async is quite a different conseption which is orthogonal to static
Related
Don't now if title is clear. Here is a piece of code from a class in charge of managing a long operation :
public class LongProcess
{
public delegate void RunningChangedEventHandler(bool running);
public event RunningChangedEventHandler RunningChanged;
private object runningLock = new object();
public bool Running
{
get { lock (runningLock) { return mRunning; } }
set
{
lock (runningLock)
{
RunningChanged.Invoke(value);
value = mRunning;
}
}
}
public void start()
{
mWorker = new BackgroundWorker();
mWorker.DoWork += Bg_DoWork;
mWorker.RunWorkerAsync();
}
private void Bg_DoWork(object sender, DoWorkEventArgs e)
{
Running = true;
// Some things to do here ... but I need Running to be equals to true and it is not
}
}
In main programm, I use LongProcess to start some tasks, it is completed by report progression etc ...
The only problem I'm facing, is that it seems that I'm unable to set "Running" to true. Even right after the call to the setter, it still keeps its old value.
Any help and explanations on how this works will be greatly appreciated !
You have your value and field the wrong way around in the setter. You need this:
public bool Running
{
get { lock (runningLock) { return mRunning; } }
set
{
lock (runningLock)
{
RunningChanged.Invoke(value);
mRunning = value; // <=== LOOK HERE
}
}
}
I am currently for the first time in need to rewrite my app into library. I have succes so far, but I need to somehow make auto repeated process, which could be started by simply camShield.start().
But I am not able to reference the enabled from anywhere. The idea here is that I would start thread with timer, which would be checking on the enabled variable. But to do that, I need another function, like stop(), which would set the enabled variable to false.
Is there any better way to implement such a function?
---EDIT----
I need to write functions CamShield.start() and CamShield.stop(), which would be able to access the CamShield.enabled variable.
Here is part of code, where I am trying to solve it (It is Class Library)
using SharpAdbClient;
using System;
using System.Diagnostics;
using System.Threading;
namespace BaReader
{
public class Private
{
public class CamShield
{
internal bool enabled = true;
public static void start()
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
Timer camShieldTimer = new Timer(tap, null, 0, 20000);
}).Start();
}
}
internal static void tap(Object o)
{
AdbClient.Instance.ExecuteRemoteCommand("input tap 600 900", Device.lookup(), null);
Debug.WriteLine("Tapped");
}
}
}
Thanks in advance for any ideas.
You have declared methods static and your variable enabled as non static so you were not able to access it,
public class CamShield
{
internal bool enabled = false;
public void start()
{
if(!enabled)
{
enabled = true;
//your code to start
}
}
public void stop()
{
if(enabled)
{
//your code to stop
enabled = false;
}
}
}
I am sure you can instantiate the CamShield class and access start and stop methods from outside.
In order to stop the thread, you need to kill it using Abort. The attached question will provide you with enough tools and knowledge to get there.
second, you cannot access the enabled because of your scope. Take another look at the code:
public class Private
{
public class CamShield
{
internal bool enabled = true;
public static void start()
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
Timer camShieldTimer = new Timer(tap, null, 0, 20000);
}).Start();
}
}
internal static void tap(Object o)
{
AdbClient.Instance.ExecuteRemoteCommand("input tap 600 900", Device.lookup(), null);
Debug.WriteLine("Tapped");
}
}
Your internal bool enabled is in the scope of CamShield class and won't be available to your tap method unless you initialize CamShield Class.
in order to use your internal bool enabled you need to declare it in your private class and then use it in tap:
public class Private
{
internal bool enabled = true;
public class CamShield
{
enabled = false;
public static void start()
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
Timer camShieldTimer = new Timer(tap, null, 0, 20000);
}).Start();
}
}
internal static void tap(Object o)
{
enabled = true;
AdbClient.Instance.ExecuteRemoteCommand("input tap 600 900", Device.lookup(), null);
Debug.WriteLine("Tapped");
}
}
This is a followup to a previous question: C# Static event null from within class
I have a class like this:
public class PlaylistModel {
public static event EventHandler PlaylistLoadError;
public static int myInt;
public static void LoadPlaylist()
{
try
{
// do some stuff, simulate exception
throw new InvalidOperationException();
}
catch(InvalidOperationException ex)
{
EventHandler handler = PlaylistLoadError;
if(handler != null)
{
PlaylistLoadError(null, null);
}
}
}
}
Else where in the program, I am setting the PlaylistLoadError EventHandler, like so:
public class MainPage {
public MainPage() {
PlaylistModel.PlaylistLoadError += MyErrorHandler;
PlaylistModel.myInt = 5;
}
public static void MyErrorHandler(object sender, EventArgs e)
{
Debug.WriteLine("There was an error");
}
}
Now, inside of LoadPlaylist, PlaylistLoadError is null and myInt is 0, despite setting them elsewhere. Later, when I create an instance of PlaylistModel, PlaylistLoadError and myInt are the correct values. So my question is this - do static functions of a class somehow access different versions of static class variables? I have checked the memory addresses of the static variables, and they are indeed different depending on if I'm inside of a non-static vs. a static function.
Static variables are static and will remain the same while the program is running unless something is called to change it.
If you want to find out what is happening I would change the field to:
private static int _myInt;
and then add:
public static int myInt
{
get { return _myInt; }
set { _myInt = value; }
}
and then add a break point at on set so you can find out when it is being changed.
I've searched Google all day and can't find the correct answer to my issue, hoping someone here can help me.
So, in the "Main" form I have the method to show a form that needs to be centered directly above the parent form (frmMain). Normally I would call ShowDialog(this) to see the parent, but for some reason I have to set the loadNewsFeedItem to static in order to see the method from the flpNewsFeedHeader : Label derrived class (below). The OnClick event triggers the method loadNewsFeedItem().
When I call this to set the parent, I'm getting the message "Keyword 'this' is not valid in a static property, static method, or static field initializer"
namespace NewsFeeds
{
public partial class FrmMain : Form
{
public static void loadNewsFeedItem()
{
frmNewsFeedView frmFeedView = new frmNewsFeedView(FrmFuncs.selFeedID);
frmFeedView.ShowDialog(this); // Error occurs on this line, when calling this via a static method
}
}
}
public class flpNewsFeedHeader : Label
{
private int FeedID = 0;
public int theFeedID
{
get { return FeedID; }
set { FeedID = value; }
}
protected override void OnClick(EventArgs e)
{
FrmFuncs.selFeedID = FeedID;
Thread thrShowFeed = new Thread(new ThreadStart(FrmMain.loadNewsFeedItem));
thrShowFeed.Start();
}
}
Can someone please give me a corrected code example or a hint as to how to get the loadNewsFeedItem() to be visible without setting the accessor to static, or how to work around this in a static accessor?
Thanks in advance!
Chris
Edit: used ActiveForm for owner.
public partial class FrmMain : Form
{
public static void loadNewsFeedItem(Form owner)
{
frmNewsFeedView frmFeedView = new frmNewsFeedView(FrmFuncs.selFeedID);
frmFeedView.ShowDialog(owner);
}
}
}
public class flpNewsFeedHeader : Label
{
private int FeedID = 0;
public int theFeedID
{
get { return FeedID; }
set { FeedID = value; }
}
protected override void OnClick(EventArgs e)
{
FrmFuncs.selFeedID = FeedID;
// Shouldn't need a new thread. Already on the GUI thread.
FrmMain.loadNewsFeedItem (System.Windows.Forms.Form.ActiveForm);
}
}
may be you mean this:
frmFeedView.Owner = System.Windows.Forms.Form.ActiveForm;
frmFeedView.ShowDialog();
In a static method, this is meaningless. One option is to skip the parameter
frmFeedView.ShowDialog();
The other option is to setup a static variable as shown below (but beware, it can have side effects if you try to open multiple instances of FrmMain)
public partial class FrmMain : Form
{
private static FrmMain staticInstance;
public FrmMain()
{
staticInstance = this;
InitializeComponent();
...
}
public static void loadNewsFeedItem()
{
frmNewsFeedView frmFeedView = new frmNewsFeedView(FrmFuncs.selFeedID);
frmFeedView.ShowDialog(staticInstance );
}
I couldn't describe the title of my question the best,I'm sorry.
Currently,I use Invoke to access the properties on my form,It works perfect,but I have a function for each property,which is quite not comfortable.
public static void EnableLogin(int enabled)
{
var form = Form.ActiveForm as FormMain;
if (form != null)
form.EnableLogin = enabled;
}
public static void EnableConfirm(int enabled)
{
var form = Form.ActiveForm as FormMain;
if (form != null)
form.EnableConfirm = enabled;
}
public static void EnableRetry(int enabled)
{
var form = Form.ActiveForm as FormMain;
if (form != null)
form.EnableRetry = enabled;
}
public static void EnableTABLogin(int enabled)
{
var form = Form.ActiveForm as FormMain;
if (form != null)
form.EnableTABLogin = enabled;
}
Each of these functions looks like that
public int EnableLogin
{
set
{
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
if (value == 0)
this.btnLogin.Enabled = false;
else
this.btnLogin.Enabled = true;
});
}
else
{
if (value == 0)
this.btnLogin.Enabled = false;
else
this.btnLogin.Enabled = true;
}
}
}
My question is,can't I do it like that
public static void EnableObject(object name)
{
var form = Form.ActiveForm as FormMain;
if (form != null)
form.Enable + name = enabled;
}
It's definitely not that way,I couldn't think of something more OO,but instead of writing tons of functions with same code,can't I use one by passing the object I'd like to change?
You could create a method that takes an delegate parameter describing the action to perform. Then you could get rid of the repeated code.
Here is an example: I create a public method called PerformAction on my form. It takes an Action<MainForm> delegate as argument; this delegate describes the action that should be taken.
The instance method should be used when possible, but for completeness I created a static version that gets the Form instance from Form.ActiveForm.
The code looks like this:
using System;
using System.Windows.Forms;
namespace WinFormTest
{
public partial class MainForm : Form
{
public void PerformAction(Action<MainForm> action)
{
if (InvokeRequired)
Invoke(action,this);
else
action(this);
}
public static void PerformActionOnMainForm(Action<MainForm> action)
{
var form = ActiveForm as MainForm;
if ( form!= null)
form.PerformAction(action);
}
}
}
And can then be used like this from another thread:
MainForm.PerformActionOnMainForm(form => form.Text = "My form");
// The action can also be a code block or a method:
MainForm.PerformActionOnMainForm(form =>
{
form.Width = 200;
form.Height = 300;
form.Left = 100;
form.Top = 200;
});
PerformAction could also be made generic so you can use it on any of your forms. Then the signature would be:
public void PerformAction<T>(Action<T> action)
where T : Form
{
...
}
It would make sense to declare it like this if you have a common base class that is shared amongst your forms. Alternatively, you could create a helper class containing the method.
I asked a similar question but for WPF, the principle is the same though. Modifying the answer that was provided to me by Jon skeet for your question you could use something like this:
public static void InvokeIfNecessary(Form form, MethodInvoker action)
{
if (form.InvokeRequired)
{
form.Invoke(DispatcherPriority.Normal, action);
}
else
{
action();
}
}
public static void EnableLogin(int enabled)
{
var form = Form.ActiveForm as FormMain;
if (form != null)
InvokeIfNecessary(form, delegate { form.btnLogin.Enabled = (enabled != 0) });
}
Edit: Changed from using form.Dispatcher.
You can move the reused functionality into two sperate static methods (one extension) which will greatly simplify what you have in the static helpers and properties.
public static class FormHelpers
{
public static void InvokeOnActive<TForm>(Action<TForm> action)
where TForm : Form
{
TForm activeForm = Form.ActiveForm as TForm;
if (activeForm != null)
activeForm.InvokeEx(f => { action(f); return f; });
}
}
public static class ControlExtensions
{
public static TResult InvokeEx<TControl, TResult>(this TControl control,
Func<TControl, TResult> func)
where TControl : Control
{
if (control.InvokeRequired)
return (TResult)control.Invoke(func, control);
else
return func(control);
}
}
And for your properties:
public int EnableLogin
{
set { this.InvokeEx(f => f.btnLogin.Enabled = value == 0); }
}
And for your static helpers:
public static void EnableLogin(int enabled)
{
FormHelpers.InvokeOnActive<FormMain>(f => f.EnableLogin = enabled);
}