I need to add my list to my listbox. I searched through all the questions on this site but none work I always get things like listbox1.spelers in my listbox.
Here is the code I have now.
private void btnAdd_Click(object sender, EventArgs e)
{
Speler speler1 = new Speler(tbNaam.Text, tbAge.Text);
List<Speler> spelers = new List<Speler>();
spelers.Add(speler1);
listBox1.DataSource = spelers;
}
Also tried with the ToArray but it still didn't work.
SOLVED
You're re-binding the control to a list of exactly one element every time. So the control will only ever have one element.
Keep the list in a higher scope. For example, if this class is persistent in memory (that is, not a web application) then make it a class-level member:
private List<Speler> spelers = new List<Speler>();
private void btnAdd_Click(object sender, EventArgs e)
{
Speler speler1 = new Speler(tbNaam.Text, tbAge.Text);
spelers.Add(speler1);
listBox1.DataSource = spelers;
// maybe call listBox1.DataBind() here? it's been a while since I've had to use forms
}
That way you're always adding another element to the same list, instead of creating a new list every time.
If you are using Windows Forms application, you can use a BindingDource:
Speler speler1 = new Speler(tbNaam.Text, tbAge.Text);
List<Speler> spelers = new List<Speler>();
spelers.Add(speler1);
var bs = new BindingSource();
bs.DataSource = spelers;
listBox1.DataSource = bs;
Good example is here : Console App
using System;
namespace Enumeration
{
using System;
using System.Collections;
// implements IEnumerable
class ListBoxTest : IEnumerable
{
private string[] strings;
private int ctr = 0;
// private nested implementation of ListBoxEnumerator
private class ListBoxEnumerator : IEnumerator
{
// member fields of the nested ListBoxEnumerator class
private ListBoxTest currentListBox;
private int index;
// public within the private implementation
// thus, private within ListBoxTest
public ListBoxEnumerator(ListBoxTest currentListBox)
{
// a particular ListBoxTest instance is
// passed in, hold a reference to it
// in the member variable currentListBox.
this.currentListBox = currentListBox;
index = -1;
}
// Increment the index and make sure the
// value is valid
public bool MoveNext()
{
index++;
if (index >= currentListBox.strings.Length)
return false;
else
return true;
}
public void Reset()
{
index = -1;
}
// Current property defined as the
// last string added to the listbox
public object Current
{
get
{
return(currentListBox[index]);
}
}
} // end nested class
// Enumerable classes can return an enumerator
public IEnumerator GetEnumerator()
{
return (IEnumerator) new ListBoxEnumerator(this);
}
// initialize the listbox with strings
public ListBoxTest(params string[] initialStrings)
{
// allocate space for the strings
strings = new String[8];
// copy the strings passed in to the constructor
foreach (string s in initialStrings)
{
strings[ctr++] = s;
}
}
// add a single string to the end of the listbox
public void Add(string theString)
{
strings[ctr] = theString;
ctr++;
}
// allow array-like access
public string this[int index]
{
get
{
if (index < 0 || index >= strings.Length)
{
// handle bad index
}
return strings[index];
}
set
{
strings[index] = value;
}
}
// publish how many strings you hold
public int GetNumEntries()
{
return ctr;
}
}
public class EnumerationTester
{
public void Run()
{
// create a new listbox and initialize
ListBoxTest currentListBox =
new ListBoxTest("Hello", "World");
// add a few strings
currentListBox.Add("Who");
currentListBox.Add("Is");
currentListBox.Add("John");
currentListBox.Add("Galt");
// test the access
string subst = "Universe";
currentListBox[1] = subst;
// access all the strings
foreach (string s in currentListBox)
{
Console.WriteLine("Value: {0}", s);
}
}
[STAThread]
static void Main()
{
EnumerationTester t = new EnumerationTester();
t.Run();
}
}
}
Related
I am reading a file into a list and then want a button to pull a random entry from the list. I can do this in VB but am fairly new to c#. I know I have to make the list public, but I'm getting increasingly frustrated.
The code below reads the file to a list and then a listbox.
namespace texttoarray
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int counter = 0;
string line;
var list = new List<string>();
var file = new StreamReader(#"list.txt");
while ((line = file.ReadLine()) != null)
{
list.Add(line);
counter++;
}
listBox2.DataSource = list;
var rnd = new Random();
}
}
}
If you want to process some information inside one method and use this processed information inside another method, you can:
pass the information as an argument to the second method
keep the information inside your class and use it inside any method
I'll assume the second approach for you, so you can do something like this:
static class Program
{
// list inside your class with the information you need
private static List<string> fileLines;
private static void Main(string[] args)
{
// call the method to read your file and create the list
FirstMethod();
// second method to get a random line, in this case, will return the string
var result = SecondMethod();
Console.WriteLine(result);
Console.ReadLine();
}
private static void FirstMethod()
{
// with this approach you can load one line per string inside your List<>
var yourFile = File.ReadAllLines("C:\\test.txt");
fileLines = new List<string>(yourFile);
}
private static string SecondMethod()
{
// random number starting with 0 and maximum to your list size
var rnd = new Random();
return fileLines[rnd.Next(0, fileLines.Count)];
}
}
I'm looking for a List<T> type class in .NET which behaves similar to List<T> but doesn't de-allocate its memory when Clear() is called - only resets the Size property.
My aim is to use this class in a memory pool, so I want the memory to be maintained, but have the caller use the class as though it were a standard list, but to avoid lots of memory re-allocations.
If this already exists please let me know as it will save time optimizing, testing and debugging this code.
Here is a mockup of what I'm hoping to find in the .NET library:
public class ReusableList<T>
{
#region Static Properties
private static long InitialCapacity = 1000000;
private static int CapacityIncreaseRate = 10000;
#endregion
#region Properties
public long Size
{
get
{
return this._size;
}
private set
{
this._size = 0;
}
}
private long _size = 0;
private long RealSize
{
get
{
return this._realSize;
}
set
{
this._realSize = value;
}
}
private long _realSize = 0;
private T[] Data
{
set
{
this._data = value;
}
get
{
return this._data;
}
}
private T[] _data = null;
#endregion
#region Operators
public T this[long index]
{
get
{
return this.Data[index];
}
set
{
this.Data[index] = value;
}
}
#endregion
#region Public Methods
public ReusableList()
{
this.Rebuild();
}
public void Add(T item)
{
this.Data[this.Size] = item;
this._size++;
if (this.Size >= this.RealSize)
{
this.IncreaseSizeOfList();
}
}
public void Clear()
{
this.Size = 0;
}
#endregion
#region Private Methods
private void Rebuild()
{
this.Data = null;
this.Data = new T[ReusableList<T>.InitialCapacity];
this.Size = 0;
this.RealSize = ReusableList<T>.InitialCapacity;
}
private void IncreaseSizeOfList()
{
if (this.Size < this.RealSize)
return;
var newData = new T[this.RealSize + ReusableList<T>.CapacityIncreaseRate];
Array.Copy(this.Data, newData, this.RealSize);
this.Data = newData;
this.RealSize += ReusableList<T>.CapacityIncreaseRate;
}
#endregion
}
As far as I understand, this is default behavior of List<T>.
When you add items to list, it allocates new memory, if needed. When you remove items (or even clear list at all), it neither "frees" memory nor decreases size of internal array.
The only way to decrease internal array is to decrease Capacity.
You can look into source code yourself. E.g., here's Clear method:
public void Clear()
{
if (_size > 0)
{
Array.Clear(_items, 0, _size);
_size = 0;
}
_version++;
}
As you can see, here's only setting array items to defaults and setting size to 0.
You can store a backup of internal list.
public class ReusableList<T> : List<T>
{
private List<T> backup;
public void Clear(bool purge)
{
if (purge)
backup?.Clear();
else
backup = this.ToList();
base.Clear();
}
public new void Clear()
{
this.Clear(false);
}
}
I have a form that has a button to get a method executed in another class.
Code on the form:
public delegate void CustomPreviewCreate();
public static event CustomPreviewCreate CustomPreviewCreate_Do;
private void CreatePreview()
{
if (CustomPreviewCreate_Do !=null)
{
CustomPreviewCreate_Do();
}
}
This event then gets handled in another class. What I would like to achieve is that I can feed back to the form some form of return value if the method correctly executed.
What I tried so far does not get me the result.
Here is the code:
public void Initialize()
{
SubAsstViewPartControl.CustomPreviewCreate_Do += SubAsstViewPartControl_CustomPreviewCreate_Do;
// this gives me a the compiler error that the return type is wrong
}
private bool SubAsstViewPartControl_CustomPreviewCreate_Do()
{
// do stuff
return false;
}
Is there any direct way to return value from an event handler or I need to use a separate static field to store the event result in?
Update:
Per #Jon's comment, which seemed the simplest to me, I added an answer below demonstrating the simplest approach.
The common approach is to encapsulate your value in the type of EventArgs your event expects. For example, the Framework's CancelEventArgs contains a settable bool Cancel property, allowing each CancelEventHandler to assign a value. The sender can then read the property after the event has been invoked. You could also use a container-like EventArgs class if you want to collect separate values from individual event handlers. For example:
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
public class SingleValueEventArgs : EventArgs
{
public int Value { get; set; }
}
public class MultiValueEventArgs : EventArgs
{
private List<int> _values = new List<int>(); // Private to prevent handlers from messing with each others' values
public IEnumerable<int> Values
{
get { return _values; }
}
public void AddValue(int value) { _values.Add(value); }
}
public class Exposer
{
public event EventHandler<SingleValueEventArgs> WantSingleValue;
public event EventHandler<MultiValueEventArgs> WantMultipleValues;
public void Run()
{
if (WantSingleValue != null)
{
var args = new SingleValueEventArgs();
WantSingleValue(this, args);
Console.WriteLine("Last handler produced " + args.Value.ToString());
}
if (WantMultipleValues != null)
{
var args = new MultiValueEventArgs();
WantMultipleValues(this, args);
foreach (var value in args.Values)
{
Console.WriteLine("A handler produced " + value.ToString());
}
}
}
}
public class Handler
{
private int _value;
public Handler(Exposer exposer, int value)
{
_value = value;
exposer.WantSingleValue += exposer_WantSingleValue;
exposer.WantMultipleValues += exposer_WantMultipleValues;
}
void exposer_WantSingleValue(object sender, SingleValueEventArgs e)
{
Console.WriteLine("Handler assigning " + _value.ToString());
e.Value = _value;
}
void exposer_WantMultipleValues(object sender, MultiValueEventArgs e)
{
Console.WriteLine("Handler adding " + _value.ToString());
e.AddValue(_value);
}
}
class Program
{
static void Main(string[] args)
{
var exposer = new Exposer();
for (var i = 0; i < 5; i++)
{
new Handler(exposer, i);
}
exposer.Run();
}
}
}
Per Jon Skeet's comment, which seemed the simplest to me, the simplest approach seems to be as follows:
public delegate bool CustomPreviewCreate(); // here we declare a return type
public static event CustomPreviewCreate CustomPreviewCreate_Do;
private void CreatePreview()
{
if (CustomPreviewCreate_Do !=null)
{
bool returnval = CustomPreviewCreate_Do();
}
}
And then:
// the method is declared to return the same type
bool SubAsstViewPartControl_CustomPreviewCreate_Do()
{
// do stuff
return true; // return the value of the type declared
}
I have 2 Forms: V.Batch and V.BatchEdit and a Class: M.Batch
In V.Batch there is a DataGrid. I want to pass the value I get from the DataGrid to V.BatchEdit and the get set method is in M.Batch.
The problem here is that the value isn't passed properly in V.BatchEdit. It returns 0.
Here is the code
V.Batch:
M.Batch bt;
public Batch()
{
bt = new M.Batch();
InitializeComponent();
}
private void metroButton3_Click_1(object sender, EventArgs e)
{
bt.batchNum = Convert.ToInt32((metroGrid2.CurrentCell.Value).ToString());
V.BatchEdit bEdit = new V.BatchEdit();
this.Hide();
bEdit.Show();
}
M.Batch:
public int batchNum;
public int BatchNum
{
set { batchNum = value; }
get { return batchNum; }
}
V.BatchEdit
static M.Batch bt = new M.Batch();
DataSet a = bt.getBatch(bt.batchNum);
public BatchEdit()
{
db = new Database();
InitializeComponent();
System.Windows.Forms.MessageBox.Show(bt.batchNum.ToString() + "Batchedit");
try
{
metroTextBox1.Text = a.Tables[0].Rows[0][2].ToString();
}
catch (Exception exceptionObj)
{
MessageBox.Show(exceptionObj.Message.ToString());
}
}
I'm new to coding and c#. I'm not sure if I placed static even though it should not be static or what.
Yes, you are using static improperly here.
The easiest way to see what's going wrong is to notice that you are calling new M.Batch() twice. That means you have two different instances of M.Batch in your application. And nowhere in your code do you attempt to share those instances.
What you should be doing is passing your instance of M.Batch from one form to another, e.g. in the constructor:
// V.Batch
bt.batchNum = Convert.ToInt32((metroGrid2.CurrentCell.Value).ToString());
V.BatchEdit bEdit = new V.BatchEdit(bt);
this.Hide();
bEdit.Show();
// V.BatchEdit
private M.Batch bt;
private DataSet a;
public BatchEdit(M.Batch batch)
{
this.bt = batch;
this.a = this.bt.getBatch(bt.batchNum)
// Rest of your code here.
}
If You don't need the 'M.Batch' class for something else and you only use it for passing the value to V.BaychEdit, just declare a public property in V.BatchEdit like you did in M.Batch and use it like this:
V.BatchEdit bEdit = new V.BatchEdit();
bEdit.BatchNum = Convert.ToInt32((metroGrid2.CurrentCell.Value).ToString());
Your problem is that although your using statics you're still assigning a new instance to the static field.
I have an issue with data seemingly being reset to its default values.
The class is as follows (objectIDs is a simple enumeration):
public class Output_args: EventArgs {
public objectIDs outputtype;
public int internalID;
public int verdict;
public int outputID;
public long entrytime;
public Output_args Copy() {
Output_args args = new Output_args();
args.entrytime = this.entrytime;
args.internalID = this.internalID;
args.outputID = this.outputID;
args.outputtype = this.outputtype;
args.verdict = this.verdict;
return args;
}
}
The following code creates the object. It runs in a specific thread, let's say Thread1.
class Class1 {
EventWaitHandle ewh = new EventWaitHandle(false, EventResetMode.AutoReset);
public event EventHandler<Output_args> newOutput;
public void readInput(){
List<Output_args> newoutputlist = new List<Output_args>();
/*
* code to determine the outputs
*/
Output_args args = new Output_args();
args.outputtype = objectIDs.stepID;
args.internalID = step[s].ID;
args.verdict = verdict;
args.entrytime = System.DateTime.Now.Ticks;
newoutputlist.Add(args.Copy());
if (newOutput != null && newoutputlist.Count > 0) {
// several outputs are being sent sequentially but for simplicity i've removed the for-loop and decision tree
try {
newOutput(null, newoutputlist[0].Copy());
} catch (Exception) { }
}
}
}
1 of the subscribers to this event has the following code. The processor method runs on a thread of a camerafeed. The newOutput event handler is being run on Thread1.
class Class2: Form {
private Output_args lastoutput = new Output_args();
public void newOutput(object sender, Output_args args) {
lock (lastoutput) {
lastoutput = args.Copy();
}
}
public void processor(){
lock (lastoutput) {
if (lastoutput.entrytime + 10000000 > System.DateTime.Now.Ticks) {
// do something
}
}
}
}
When the eventhandler 'newOutput' of Class2 is being called, the debugger shows that the copy works as expected and 'entrytime' is given the expected number of ticks.
However, when the processor method wants to read the 'entrytime', its value is 0. All other fields also have their default value assigned.
I've tried replacing the object 'lastoutput' with a simple field of the type long and removed the locks but the results are the same: it gets assigned properly in 'newOutput' but has its default value (0) in the processor method.
Any ideas on why this is happening?
you should not lock on the object lastoutput, but on another object, because you reassign the field.
The processor start and lock on the default field instance new Output_args() initialized with default values
class Class2: Form {
private object mylock = new object();
private Output_args lastoutput;
public void newOutput(object sender, Output_args args) {
lock (mylock) {
lastoutput = args.Copy();
}
}
public void processor(){
lock (mylock) {
if (lastoutput == null) {
//nothing to consume yet
}
else if (lastoutput.entrytime + 10000000 > System.DateTime.Now.Ticks) {
// do something
}
}
}
}
but this discard lastouput if consumer is slower than producer. You can use a queue ( or another collection ) as buffer if needed.
class Class2 {
private Queue<Output_args> outputs = new Queue<Output_args>();
public void newOutput(object sender, Output_args args) {
lock (outputs) {
outputs.Enqueue(args.Copy());
}
}
public void processor(){
lock (outputs) {
if (outputs.Count > 0) {
var lastoutput = outputs.Dequeue();
if (lastoutput.entrytime + 10000000 > System.DateTime.Now.Ticks) {
// do something
}
}
}
}
}
demo: https://dotnetfiddle.net/daHVD1