I have this class wich I will make an instance for it in Form1 later that pass variables from Form1 to the class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GatherLinks
{
class WebcrawlerConfiguration
{
public string url;
public int levels;
public string mainurl;
public Dictionary<string,List<string>> localy;
public bool removeext;
public bool downloadcontent;
public int failedUrls;
public bool toCancel;
public System.Threading.ManualResetEvent busy;
public WebcrawlerConfiguration()
{
}
}
}
How do I make that this class will get the variables from Form1 ?
Each variable in the class should get the variable in Form1 when I will make an instance for the class.
Then I have this class:
class BackgroundWebCrawling
{
int counter = 0;
List<string> WebSitesToCrawl;
BackgroundWorker mainBackGroundWorker;
BackgroundWorker secondryBackGroundWorker;
WebCrawler webcrawler1;
WebcrawlerConfiguration webcrawlerCFG;
public BackgroundWebCrawling()
{
mainBackGroundWorker = new BackgroundWorker();
mainBackGroundWorker.DoWork += mainBackGroundWorker_DoWork;
}
private void mainBackGroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < WebSitesToCrawl.Count; i++)
{
if (counter >= 3)
{
Thread.Sleep(10);
}
else
{
webcrawler1 = new WebCrawler(webcrawlerCFG);
counter++;
secondryBackGroundWorker = new BackgroundWorker();
secondryBackGroundWorker.DoWork += secondryBackGroundWorker_DoWork;
}
}
}
private void secondryBackGroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
if (offlineOnline == true)
{
offlinecrawling(f, levelsToCrawl, e);
}
else
{
webcrawler1.webCrawler(
}
counter--;
}
In the bottom here im doing: webcrawler1.webCrawler(
The function webCralwer should get all the variables from the first class WebcrawlerConfiguration.
This is how the WebCrawler function looks like:
public List<string> offlinecrawling(string url, int levels, string mainurl, Dictionary<string, List<string>> localy, bool removeext, bool downloadcontent, int failedUrls, bool toCancel, System.Threading.ManualResetEvent busy)
So now when im doing webcrawler1.webCrawler(
It's asking for all the variables...But I want to pass them somehow from the WebcrawlerConfiguration.
How can I do it ?
Related
I'm fairly new to C# and am trying to create a web browser for a specific function
I have Form1 (An invisible form) that calls Form2 (The browser) and monitor to make sure Form2 is always running and if it goes idle close and reopen Form2
I think I'm having an issue with threading, which I setup to run the timer (It's the only way I could work out)
I have determined that it only fails to launch Form2 when I try to call the function from inside the thread
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using Browselite;
using System.Diagnostics;
using System.Threading;
namespace BrowseLite
{
public partial class Form1 : Form
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool SetProcessDPIAware();
public static Boolean IdleTimeoutEnabled { get; private set; }
public static int IdleTimeout { get; private set; }
public static Boolean ClearRunning { get; private set; }
public Form2 Browser { get; private set; }
public static Boolean programmaticClose { get; set; }
public static Boolean Form2Open { get; set; }
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll")]
public static extern Boolean GetLastInputInfo(ref tagLASTINPUTINFO plii);
public struct tagLASTINPUTINFO
{
public uint cbSize;
public Int32 dwTime;
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
using (RegistryKey RootKey = Registry.CurrentUser.OpenSubKey("Software\\Policies\\BrowseLite"))
{
try
{
Form1.IdleTimeout = Int32.Parse(RootKey.GetValue("IdleTimeout", -1, RegistryValueOptions.None).ToString());
if (Form1.IdleTimeout <= 0)
{
Form1.IdleTimeoutEnabled = false;
}
else
{
Form1.IdleTimeoutEnabled = true;
}
}
catch
{
Form1.IdleTimeout = 0;
Form1.IdleTimeoutEnabled = false;
}
}
}
catch
{
Form1.IdleTimeout = 0;
Form1.IdleTimeoutEnabled = false;
}
Thread Timer = new Thread(new ThreadStart(MyTimer));
Browser = new Form2();
OpenBrowser();
Timer.Start();
}
private void MyTimer()
{
while (true)
{
FormCollection OpenForms = Application.OpenForms;
foreach (Form OpenForm in OpenForms)
{
if (OpenForm.Name.Contains("Form2"))
{
Form1.Form2Open = true;
}
}
if (!Form1.Form2Open)
{
Browser.ShowDialog();
Form1.Form2Open = true;
}
tagLASTINPUTINFO LastInput = new tagLASTINPUTINFO();
Int32 IdleTime;
LastInput.cbSize = (uint)Marshal.SizeOf(LastInput);
LastInput.dwTime = 0;
if (GetLastInputInfo(ref LastInput))
{
IdleTime = System.Environment.TickCount - LastInput.dwTime;
int IdleTimeSet = IdleTimeout * 60 * 1000;
if (Form1.IdleTimeoutEnabled)
{
if (IdleTime >= IdleTimeSet)
{
if (Form1.ClearRunning == false)
{
CloseBrowser();
OpenBrowser();
}
}
else
{
Form1.ClearRunning = false;
}
}
}
Thread.Sleep(1000 * 30); //Time in seconds (30)
}
}
private void CloseBrowser()
{
Form1.programmaticClose = true;
Browser.Close();
}
private void OpenBrowser()
{
Form1.programmaticClose = false;
Form1.Form2Open = true;
Browser.ShowDialog();
}
}
}
Any help would be appreciated, but as I said... I'm not good with this.
For anyone else that stumbles onto this, I found the answer myself
If setting a variable in the thread. Instead of using
Form1.Running = true;
instead use
BeginInvoke(new Action(() => Form1.Running = true), null);
And if calling a function from within the thread use
BeginInvoke(new InvokeDelegate(FUNCTION));
This seems to have completely fixed my issue
I am trying to make a program that will track household budget in terms of salaries and expanses.
For that what I want my program to do is to generate (and delete when needed) 2 labels (name and salary) for each working person in the house.
So far I been trying all sorts of different ways, even straight up copying code from questions similar to mine to get the labels to show up, but whatever I do they never appear (even though the property 'IsDisposed' shows that the label still exists)
Here is my spaghetti code:
Forms1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Budget_Management
{
public partial class Form1 : Form
{
static Person[] person = new Person[1];
static Label[] name = new Label[1];
static Label[] salary = new Label[1];
static int numOfPeople = 0;
public Form1()
{
InitializeComponent();
Label myLabel = new Label();
myLabel.Top = 10;
myLabel.Left = 10;
MessageBox.Show(Convert.ToString(myLabel.IsDisposed));
}
private void tabPage1_Click(object sender, EventArgs e)
{
}
private void addaPersonButton_Click(object sender, EventArgs e)
{
int temp;
if (int.TryParse(salaryTextBox.Text, out temp) == true)
{
person = Program.increasePersonAmount(person, numOfPeople);
person[numOfPeople] = new Person();
person[numOfPeople].salary = Convert.ToInt32(salaryTextBox.Text);
person[numOfPeople].name = nameTextBox.Text;
name = Program.increaseLabelAmount(name, numOfPeople);
salary = Program.increaseLabelAmount(salary, numOfPeople);
Program.generateLabels(name, salary, nameTextBox.Text, Convert.ToInt32(salaryTextBox.Text), numOfPeople);
numOfPeople++;
}
else
{
MessageBox.Show("Salary is invalid number!");
}
}
}
}
Program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Budget_Management
{
static class Program
{
static int numOfSpendings;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
public static Person[] increasePersonAmount(Person[] old, int amount)
{
Person[] temp = new Person[amount + 1];
for (int i = 0; i < old.Length-1; i++)
{
temp[i] = old[i];
}
return temp;
}
public static Person[] descreasePersonAmount(Person[] old, int personToDelete, int amount)
{
Person[] temp = new Person[amount-1];
for (int i = 0, j = 0; i < old.Length; i++)
{
if (i == personToDelete)
{
}
else
{
temp[j] = old[i];
j++;
}
}
return temp;
}
public static Label[] increaseLabelAmount(Label[] old, int amount)
{
Label[] temp = new Label[amount + 1];
for (int i = 0; i < old.Length - 1; i++)
{
temp[i] = old[i];
}
return temp;
}
public static void generateLabels(Label[] nameLabel, Label[] salaryLabel, string name, int salary, int labelNum)
{
nameLabel[labelNum] = new System.Windows.Forms.Label();
nameLabel[labelNum].Text = name;
nameLabel[labelNum].Left = 10;
nameLabel[labelNum].Top = 5;
nameLabel[labelNum].Visible = true;
}
public static void deleteLabel(int labelNum)
{
}
}
}
Use the Visible property setting ir yo false when hoy need un order to hide the labels.
Put your labels on the form using the design surface, the hide them when your form initializes:
public partial class Form1 : Form
{
InitializeComponent;
label1.Visible = false;
label2.Visible = false;
//etc. etc.
}
Then, later on in your code, when you want them to appear, just set Visible to true:
public void ShowLabels()
{
label1.Visible = true;
label2.Visible = true;
//etc.
}
I'm learning C#, trying to get to grips with accessors at the moment.
I'm going nuts looking at this, I have no idea what I've done wrong:
class BankAccount
{
// *PROPERTIES*
private int _initialDeposit = 0;
// **ACCESSORS**
public int SavingsAccount
{
set
{
_initialDeposit = value;
}
get
{
return _initialDeposit;
}
}
}
The Form looks like this:
public partial class BankForm : Form
{
private BankAccount _myAccount;
public BankForm()
{
InitializeComponent();
_myAccount = new BankAccount();
}
private void initialDepositButton_Click(object sender, EventArgs e)
{
_myAccount.SavingsAccount = Convert.ToInt32(initialDepositTextBox.Text);
bankAccountListBox.Text = "Account opened with initial Deposit " + initialDepositTextBox.Text;
}
}
But I get this error:
Property or indexer must have at least one accessor
I'm not getting any errors. Move location of private BankAccount _myAccount;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace BankForm
{
public partial class BankForm : Form
{
public BankForm()
{
InitializeComponent();
_myAccount = new BankAccount();
}
private BankAccount _myAccount;
private void initialDepositButton_Click(object sender, EventArgs e)
{
_myAccount.SavingsAccount = Convert.ToInt32(initialDepositTextBox.Text);
bankAccountListBox.Text = "Account opened with initial Deposit " + initialDepositTextBox.Text;
}
}
class BankAccount
{
// *PROPERTIES*
private int _initialDeposit = 0;
// **ACCESSORS**
public int SavingsAccount
{
set
{
_initialDeposit = value;
}
get
{
return _initialDeposit;
}
}
}
}
I keep getting this error and I know why but I need help figuring out how I can solve it. The only way I have been able to add my items it to make a new form but that seems silly.
It wont work if I make all my methods static =(
I keep getting,
"An object reference is required for the non-static field, method, or
property 'Handicap_Calculator.FormMain.listViewLog'
\Form1.cs 74 13 Handicap Calculator"
Here´s my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Handicap_Calculator
{
public partial class FormMain : Form
{
//FormAddScore FormAddNewScore = new FormAddScore();
public static bool addScoreIsShown = false;
public static FormAddScore _FormAddScore;
public static ListViewItem Item;
//public static List<string> ScoreInfo = new List<string>();
public FormMain()
{
InitializeComponent();
}
public void button1_Click(object sender, EventArgs e)
{
try
{
if (_FormAddScore == null || _FormAddScore.IsDisposed)
{
_FormAddScore = new FormAddScore();
}
_FormAddScore.Show();
if (_FormAddScore.WindowState == FormWindowState.Minimized)
{
_FormAddScore.WindowState = FormWindowState.Normal;
}
_FormAddScore.BringToFront();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
public static void AddScore()
{
int Round = 1;
DateTime date = _FormAddScore.date;
string course = _FormAddScore.course;
int holes = _FormAddScore.holes;
int score = _FormAddScore.score;
float courseRating = _FormAddScore.courseRating;
float slopeRating = _FormAddScore.slopeRating;
string[] ScoreInfo = new string[7];
ScoreInfo[0] = Round.ToString();
ScoreInfo[1] = date.ToString();
ScoreInfo[2] = course;
ScoreInfo[3] = holes.ToString();
ScoreInfo[4] = score.ToString();
ScoreInfo[5] = courseRating.ToString();
ScoreInfo[6] = slopeRating.ToString();
AddToList(ScoreInfo);
}
public static void AddToList(string[] ScoreInfo)
{
Item = new ListViewItem(ScoreInfo);
//listViewLog.Items.Add(Item);
}
}
}
Edit...
Here is the class im calling it from:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Handicap_Calculator
{
public partial class FormAddScore : Form
{
public DateTime date;
public string course;
public int holes;
public int score;
public float courseRating;
public float slopeRating;
public FormAddScore()
{
InitializeComponent();
}
private void FormAddScore_FormClosing(object sender, FormClosingEventArgs e)
{
FormMain.addScoreIsShown = false;
}
public void getscore()
{
try
{
date = dateTimePicker1.Value;
course = textBoxCourse.Text;
holes = Convert.ToInt16(textBoxHoles.Text);
score = Convert.ToInt16(textBoxScore.Text);
courseRating = Convert.ToSingle(textBoxCourseRating.Text);
slopeRating = Convert.ToSingle(textBoxSlopeRating.Text);
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void button1_Click(object sender, EventArgs e)
{
getscore();
FormMain.AddScore();
}
}
}
The simple solution is to define your methods AddScore and AddToList as non-static.
public void AddScore()
{
//your code
}
public void AddToList(string[] ScoreInfo)
{
// your code
}
If you want to use static methods you should pass the instance of your Form to the method, on which you want to add items to the ListView.
public static void AddScore(FormMain mainForm)
{
//your code
AddToList(mainForm, ScoreInfo);
}
public static void AddToList(FormMain mainForm, string[] ScoreInfo)
{
// your code
}
Update:
According to your updated code the solution is to pass the instance of your FormMain to your FormAddScore when you create it. In FormAddScore you store the reference to the FormMain instance to call the methods on.
public partial class FormAddScore : Form
{
// your code
private FormMain _mainForm;
public FormAddScore(){
InitializeComponent();
}
public FormAddScore(FormMain mainForm) : this(){
_mainForm = mainForm;
}
In your FormMain when you create the instance of FormAddScore you should use the constructor that expects an instance of FormMain
_FormAddScore = new FormAddScore(this);
With this setup you can change your methods to non-static and you can call the methods of FormMain in your FormAddScore, by using the stored reference in variable _mainForm.
_mainForm.AddScore();
Instance X of a class register to the change event of instances Y of the same class.
I want to update X if Y is changed, but i dont want to use the static keyword all over the class. Is there a way to transmit the recipient of the event in the eventargs?
Here is some example code with an NUnit tests to illustrate where my problem lies exactly. I compiled and ran it. Two tests just verify the programming. The failing test illustrates my problem.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
namespace Eventtest
{
public class DependencyChain
{
public static int demonstrationcount = 0;
private String hiddenstring = "";
public String visiblestring
{
get { return hiddenstring; }
set
{
hiddenstring = value;
NotifyOnStringChanged();
}
}
private void NotifyOnStringChanged()
{
if (changed != null)
{
changed(this, EventArgs.Empty);
}
}
public EventHandler changed;
private EventHandler Observer = new EventHandler((o, e) => {
DependencyChain sender = (o as DependencyChain);
demonstrationcount++;
//THE FOLLOWING DOES NOT WORK SINCE "this" IS NOT STATIC
//DependencyChain recipient = this;
//recipient.visiblestring = sender.visiblestring;
});
public DependencyChain(string initialstring)
{
this.visiblestring = initialstring;
}
public DependencyChain(DependencyChain other)
{
this.visiblestring = other.visiblestring;
other.changed += Observer;
}
public override string ToString()
{
return visiblestring;
}
}
[TestFixture]
class Eventtest
{
[SetUp]
public void ResetStaticCounter()
{
DependencyChain.demonstrationcount = 0;
}
[Test]//PASS
public void ShouldInitialiseAndCopyValues()
{
DependencyChain Y = new DependencyChain("initial");
DependencyChain X = new DependencyChain(Y);
Assert.AreEqual(X.ToString(), Y.ToString());
}
[Test]//PASS
public void ShouldCallObserverOnChange()
{
DependencyChain Y = new DependencyChain("initial");
DependencyChain X = new DependencyChain(Y);
Assert.AreEqual(0, DependencyChain.demonstrationcount);
Y.visiblestring = "changed";
Assert.AreEqual(1, DependencyChain.demonstrationcount);
}
[Test]//FAIL
public void ShouldChangeStringOnChange()
{
DependencyChain Y = new DependencyChain("initial");
DependencyChain X = new DependencyChain(Y);
Y.visiblestring = "changed";
Assert.AreEqual(X.ToString(), Y.ToString());
}
}
}
I think you only have to move the initialization of Observer to a constructor of DependencyChain, so you can capture this.