i want from my program to select a listbox item and then update it.i have a list ecoItems.Eco is a class with 2 store variables,one string and one double variable.SetEcoValues is a set Method take two values,one string and one double.i try this code but don't change anything.any suggestions?
private void Update_Click(object sender, EventArgs e)
{
Eco y;
y = ecoItems.ElementAt<Eco>(listBox1.SelectedIndex);
y.SetEcoValues(textBox1.Text,Convert.ToDouble(textBox2.Text));
listBox5.Items.Insert(listBox1.SelectedIndex, y);
}
}
Using your code and what I would guess is your class, I'd do something like this:
class Eco {
public Eco() { }
public void SetEcoValues(string text, double value) {
Text = text;
Value = value;
}
public string Text { get; set; }
public double Value { get; set; }
public override string ToString() {
if (!String.IsNullOrEmpty(Text)) {
return Text;
}
return base.ToString();
}
}
ListView listView1; // initialized somewhere, I presume.
void Update_Click(object sender, EventArgs e) {
if ((listView1.SelectedItems != null) || (0 < listView1.SelectedItems.Count)) {
ListViewItem item = listView1.SelectedItems[0];
Eco y = item.Tag as Eco;
if (y == null) {
y = new Eco();
}
y.SetEcoValues(textBox1.Text, Convert.ToDouble(textBox2.Text));
item.Text = y.Text;
if (item.SubItems.Count < 2) {
item.SubItems.Add(y.Value.ToString());
} else {
item.SubItems[1].Text = y.Value.ToString();
}
item.Tag = y;
}
}
You're not actually getting the ListItem anywhere, and trying to add something to the ListBox which isn't a ListItem. You could try something like so:
ListItem Item = listBox1.SelectedItem;
//Update the Text and Values
Item.Text = textBox1.Text,;
Item.Value = textBox2.Text;
Or... if you have the ListBox Bound to your list of Ecos and want it updated, instead of listBox5.Items.Insert... you would need to re bind it.
listBox5.DataSource = y;
listBox5.DataBind();
Related
I made an mp3 player in C#. If I select the songs at once, they automatically play one after the other, but when it comes to a song I added later, I get a "System.IndexOutOfRangeException" error. When I add music later, I want the song to play automatically one after the other, how can I do that?
string[] yol, dosya;
private void Btn_Muzik_Ekle_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Multiselect = true;
if (ofd.ShowDialog()==System.Windows.Forms.DialogResult.OK)
{
dosya = ofd.SafeFileNames;
yol = ofd.FileNames;
for (int x = 0; x < dosya.Length; x++)
{
Lb_Muzik_Listesi.Items.Add(dosya[x]);
}
}
}
private void Lb_Muzik_Listesi_SelectedIndexChanged(object sender, EventArgs e)
{
//This Is Where I Got The Error
OynatmaEkranı.URL = yol[Lb_Muzik_Listesi.SelectedIndex];
OynatmaEkranı.Ctlcontrols.play();
try
{
var file = TagLib.File.Create(yol[Lb_Muzik_Listesi.SelectedIndex]);
var bin = (byte[])(file.Tag.Pictures[0].Data.Data);
Pb_Muzik_Kapak.Image = Image.FromStream(new MemoryStream(bin));
}
catch
{
}
}
private void Zamanlayıcı_Tick(object sender, EventArgs e) //Timer
{
if (OynatmaEkranı.playState==WMPLib.WMPPlayState.wmppsPlaying)
{
Pb_Muzik.Maximum=(int)OynatmaEkranı.Ctlcontrols.currentItem.duration;
Pb_Muzik.Value = (int)OynatmaEkranı.Ctlcontrols.currentPosition;
try
{
Lbl_Muzik_Sure.Text = OynatmaEkranı.Ctlcontrols.currentPositionString;
Lbl_Muzik_Bitis.Text = OynatmaEkranı.Ctlcontrols.currentItem
.durationString.ToString();
}
catch
{
}
}
if (Pb_Muzik.Value==Pb_Muzik.Maximum)
{
if (Lb_Muzik_Listesi.SelectedIndex<Lb_Muzik_Listesi.Items.Count-1)
{
Lb_Muzik_Listesi.SelectedIndex = Lb_Muzik_Listesi.SelectedIndex + 1;
}
}
}
You can avoid this problem managing your data in the ListBox. Create a class with your required info (the file and the name):
public class MuzikItem
{
public MuzikItem(string file)
{
this.Text = System.IO.Path.GetFileNameWithoutExtension(file);
this.Url = file;
}
public string Text { get; set; }
public string Url { get; set; }
public override string ToString()
{
// This is the text to show in ListBox
return this.Text;
}
}
Add items to the ListBox using this class:
foreach (var file in ofd.FileNames)
{
var item = new MuzikItem(file);
Lb_Muzik_Listesi.Items.Add(item);
}
And use it:
var item = Lb_Muzik_Listesi.SelectedItem as MuzikItem;
if (item != null)
{
OynatmaEkranı.URL = item.Url;
OynatmaEkranı.Ctlcontrols.play();
try
{
var file = TagLib.File.Create(item.Url);
var bin = (byte[])file.Tag.Pictures[0].Data.Data;
Pb_Muzik_Kapak.Image = Image.FromStream(new MemoryStream(bin));
}
catch
{
}
}
You try to get the selected item as a MuzikItem (all your items are of this class so this return null only when no item is selected) and with this, you have the Url.
UPDATE
I like manage this things with events. In your Ticks methods:
if (Pb_Muzik.Value == Pb_Muzik.Maximum)
{
OnSongFinished();
}
And create a method to manage this event:
private void OnSongFinished()
{
if (Lb_Muzik_Listesi.SelectedIndex < Lb_Muzik_Listesi.Items.Count - 1)
{
Lb_Muzik_Listesi.SelectedIndex = Lb_Muzik_Listesi.SelectedIndex + 1;
}
else
{
// Stop the player
OynatmaEkrani.Ctlcontrols.stop();
}
}
I'm currently stuck on this for 2 hours and did everything I could to find answers but none yet!
public class Snack
{
public string snack { get; set; }
public double amount { get; set; }
public int price { get; set; }
public Snacks snacks;
public enum Snacks
{
friet,
kroket,
frikandel,
Burger,
}
}
In the load method, I'm initializing my ListView:
private void load()
{
lstSnacks.View = View.Details;
lstSnacks.Columns.Add("snack");
lstSnacks.Columns.Add("amount");
lstSnacks.Columns.Add("price");
cmbSnack.Items.AddRange(Enum.GetNames(typeof(Snack.Snacks)));
cmbSnack.SelectedIndex = (int)Snack.Snacks.friet;
}
After that, I have a button where I add some snacks with the amount entered in the textbox and a fixed price:
private void btnAdd_Click(object sender, EventArgs e)
{
if (!lstSnacks.Items.ContainsKey(cmbSnack.SelectedItem.ToString()))
{
double totalprice = 0;
Snack snack1 = new Snack();
snack1.snack = cmbSnack.SelectedItem.ToString(); ;
snack1.amount = Convert.ToDouble(txtAmount.Text);
ListViewItem item = lstSnacks.Items.Add(cmbSnack.SelectedItem.ToString());
item.SubItems.Add(snack1.amount.ToString());
if (cmbSnack.SelectedIndex == 0)
{
snack1.price = (int)(snack1.amount * 2.50);
item.SubItems.Add(snack1.price.ToString());
}
}
I need to look into my ListView and add a snack if it's not already there. If it is, it should tell you that it's already in there, but items.ContainsKey is not working for me properly. What am I doing wrong?
The line...
ListViewItem item = lstSnacks.Items.Add(cmbSnack.SelectedItem.ToString());
...sets the Text property of the ListViewItem. To be able to use ContainsKey(), you need to also set its Name property.
One more thing: Consider using double.TryParse() instead of Convert.ToDouble() because there's no guarantee that the user will enter a valid number. When dealing with user input, always favor the .TryParse() methods over Convert.ToXXXX() or .Parse().
I would change the code into something like this:
string itemName = cmbSnack.SelectedItem.ToString();
if (lstSnacks.Items.ContainsKey(itemName))
{
MessageBox.Show("The item already exists in the list.", "Duplicate item");
return;
}
if (!double.TryParse(txtAmount.Text, out double amount))
{
MessageBox.Show("Please enter a valid amount.", "Incorrect 'Amount' value");
return;
}
double totalprice = 0;
Snack snack1 = new Snack();
snack1.snack = itemName;
snack1.amount = amount;
ListViewItem item = lstSnacks.Items.Add(itemName);
item.Name = itemName;
item.SubItems.Add(snack1.amount.ToString());
if (cmbSnack.SelectedIndex == 0)
{
snack1.price = (int)(snack1.amount * 2.50);
item.SubItems.Add(snack1.price.ToString());
}
I want to show the attributes of an object when I click on a button in Windows Forms using c# and I don't know how to do it. Part of my code looks like this until now. I'm a beginner in c#.
class Pizza: ICloneable
{
private string nume;
private int nrIngrediente;
private string[] ingrediente;
public Pizza()
{
nume = "Margherita";
nrIngrediente = 2;
ingrediente = new string[nrIngrediente];
for (int i = 0; i < nrIngrediente; i++)
{
ingrediente[0] = "Sos rosii";
ingrediente[1] = "Mozzarella";
}
}
public Pizza(string den, int nri, string[] ing)
{
nume = den;
nrIngrediente = nri;
ingrediente = new string[nrIngrediente];
for (int i = 0; i < nrIngrediente; i++)
ingrediente[i] = ing[i];
}
public Pizza(Pizza p)
{
nume = p.nume;
nrIngrediente = p.nrIngrediente;
ingrediente = new string[nrIngrediente];
for (int i = 0; i < nrIngrediente; i++)
ingrediente[i] = p.ingrediente[i];
}
public string PizzaName
{
get { return nume; }
set { nume = value; }
}
public int PizzaNrIng
{
get { return nrIngrediente; }
set { nrIngrediente = value; }
//also, i don't know how to write the getter and setter for this one
public string PizzaIngredients
//{
// get
// {
// for(int i=0;i<nrIngrediente;i++)
// return ingrediente[i];
// }
// set { ingrediente = value; }
//}
And now, the form code is the following(note that i designed it already):
public partial class ListaPizza : Form
{
public ListaPizza()
{
InitializeComponent();
}
private void Margherita_Click(object sender, EventArgs e)
{
string[] ingrMargh = new string[2] { "Sos rosii", "Mozzarella" };
Pizza Margherita = new Pizza("Margherita", 2, ingrMargh);
//Show(Margherita);
//here i want the object created above to be shown in a messagebox when i click the button in the form but i don't know how
}
}
Thank you!
MessageBox.Show();
has to be a string value so any parts of your object that is not a string will need the .ToString() method
Or if you want to customize the view you could pass the object to a new form and create a whole nice layout for it with the designer.
You can set the getter and setter in below way.
public string PizzaIngredients
{
get
{
return String.Join(",",nringrediente);
}
set
{
nringrediente = value.Split(',');
}
}
And Show(Margherita); can be implemented like in Pizza Class :
public string GetDisplayMessageForPizza()
{
return "My Pizza is " + nume + ". It contains " + nringrediente + " ingredients : " + PizzaIngredients;
}
And in form ListaPizza :
private void Margherita_Click(object sender, EventArgs e)
{
string[] ingrMargh = new string[2] { "Sos rosii", "Mozzarella" };
Pizza Margherita = new Pizza("Margherita", 2, ingrMargh);
MessageBox.Show(Margherita.GetDisplayMessageForPizza());
}
As for the getter - you should return an array of strings, not just a string:
public string[] PizzaIngredients
{
get
{
ingrediente;
}
set
{
ingrediente = value;
}
}
As for the showing - just use MessageBox.Show():
MessageBox.Show(string.Format("{0} {1}", Margherita.Name, Margherita.nrIngrediente));
I'm using Entity Framework to throw together a combobox with values from my MSSQL database using the following
using (var context = new Entity())
{
var things = (from p in context.Stuff
where ((p.SourceId == StuffId && p.Domain.Value == "Stuff")
|| (p.SourceId == OtherStuffId && p.Domain.Value == "OtherStuff"))
&& p.Done == true orderby p.StuffId
select p);
foreach(var stuff in things)
cboRejectTask.Items.Add(stuff.StuffId + ": " + stuff.StuffType.Description + " " + stuff.StuffType.DisplayName);
}
I'd like to assign values to each row so that when it comes time to grab what the user selected I don't have to do string manipulation to get what I want. I don't want to use a datasource if possible.
Solution:
Given there isn't a better way to do this than creating a custom class I went ahead and did so using the selected answer's code modified a bit for long-term use. (note: you could really use any given object as long as ToString() returned the "display text" and it had a Tag or any writeable property compatible with your needs)
public class ComboBoxItem
{
public string Display;
public object Value;
public override string ToString()
{
return Display;
}
}
Given this code I can now change my code to the following:
using (var context = new Entity())
{
var things = (from p in context.Stuff
where ((p.SourceId == StuffId && p.Domain.Value == "Stuff")
|| (p.SourceId == OtherStuffId && p.Domain.Value == "OtherStuff"))
&& p.Done == true orderby p.StuffId
select p);
foreach(var stuff in things)
cboRejectTask.Items.Add(new ComboBoxItem() { Display = stuff.StuffId + ": " + stuff.StuffType.Description + " " + stuff.StuffType.DisplayName, Value = stuff.StuffId });
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var cbi1 = new ComboBoxItem("Item 1") { Id = 1 };
var cbi2 = new ComboBoxItem("Item 2") { Id = 2 };
var cbi3 = new ComboBoxItem("Item 3") { Id = 3 };
comboBox1.Items.Add(cbi1);
comboBox1.Items.Add(cbi2);
comboBox1.Items.Add(cbi3);
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
var id = ((ComboBoxItem)comboBox1.SelectedItem).Id;
MessageBox.Show(id.ToString());
}
}
public class ComboBoxItem
{
private readonly string text;
public int Id { get; set; }
public ComboBoxItem(string text)
{
this.text = text;
}
public override string ToString()
{
return text;
}
}
I think you might find this usefull:
comboBox1.Items.Add(1);
comboBox1.Items.Add(2);
comboBox1.Items.Add(3);
private void comboBox1_Format(object sender, ListControlConvertEventArgs e)
{
//this will set what gets displayed in the combobox, but does not change the value.
e.Value = "display value";
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
MessageBox.Show((sender as ComboBox).SelectedItem.ToString());
}
I have a class that implements the INotifyPropertyChanged interface.
If I create a new instance of the object, the PropertyChanged event gets set after I retrieve a value from it.
Example:
MyItem itm = new MyItem(); //MyItem.PropertyChanged == null
string test = itm.Value; //MyItem.PropertyChanged != null
If I assign itm the value of another MyItem, the PropertyChanged event remains null.
Example:
itm = (MyItem)cboMyItemsCombobox.SelectedItem; // Properties for itm change to the values
// of the selected item, but PropertyChanged
// == null
I believe the problem lies partially in my custom constructor for the class, but I'm not entirely sure.
The goal is to have a variable to hold data for a record, called mnuitm, that is bound to
3 textbox objects. When the text in a textbox changes, the change is made to the property in mnuitm. When the property in mnuitm is changed, the change is made in the textbox.
This works if I create a new MenuItem and assign the values individually, but does not work if I assign an already populated MenuItem to mnuitm.
Here is my actual code for (hopefully) more clearity on the issue.
public partial class frmMenuItems : Form
{
private class MenuItem : INotifyPropertyChanged
{
private Int32 mid;
private string txt;
private string url;
private string scp;
public MenuItem() { }
public MenuItem(Int32 id, string txt, string url, string scp)
{
ID = id;
Text = txt;
URL = url;
Script = scp;
}
public Int32 ID
{
get
{
return mid;
}
set
{
if (mid != value)
{
mid = value;
NotifyPropertyChanged("ID");
}
}
}
public string Text {
get
{
return txt;
}
set
{
if (txt != value)
{
txt = value;
NotifyPropertyChanged("Text");
}
}
}
public string URL {
get
{
return url;
}
set
{
if (url != value)
{
url = value;
NotifyPropertyChanged("URL");
}
}
}
public string Script {
get
{
return scp;
}
set
{
if (scp != value)
{
scp = value;
NotifyPropertyChanged("Script");
}
}
}
public void Clear()
{
ID = 0;
Text = "";
URL = "";
Script = "";
}
public override string ToString()
{
return Text;
}
private void NotifyPropertyChanged(string inf)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(inf));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
private MenuItem mnuitm;
private MySqlConnection sqlcon;
public frmMenuItems()
{
InitializeComponent();
}
private void btnClose_Click(object sender, EventArgs e)
{
this.Close();
}
private void btnCancel_Click(object sender, EventArgs e)
{
mnuitm.Clear();
}
private void frmMenuItems_Load(object sender, EventArgs e)
{
string constr = "server={0};uid={1};pwd={2};database={3};";
DBItem dbi = CountyDataManager.CountyData.DBConnection;
constr = string.Format(constr, [MyHost], [MyUsername], [MyPassword], [MyDatabase]);
sqlcon = new MySqlConnection(constr);
sqlcon.Open();
mnuitm = new MenuItem();
SetBindings();
RefreshList();
}
private void SetBindings()
{
txtMenuText.DataBindings.Clear();
txtURL.DataBindings.Clear();
txtScript.DataBindings.Clear();
txtMenuText.DataBindings.Add("Text", mnuitm, "Text");
txtURL.DataBindings.Add("Text", mnuitm, "URL");
txtScript.DataBindings.Add("Text", mnuitm, "Script");
}
private void RefreshList()
{
using (MySqlCommand cmd = new MySqlCommand("SELECT `menuid`,`menutext`,`url`,`script` FROM tblindexmenu ORDER BY `menutext`", sqlcon))
{
lstMenuItems.Items.Clear();
using (MySqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
lstMenuItems.Items.Add(new MenuItem(Int32.Parse(rdr[0].ToString()), rdr[1].ToString(),rdr[2].ToString(),rdr[3].ToString()));
}
}
}
}
private void frmMenuItems_FormClosing(object sender, FormClosingEventArgs e)
{
sqlcon.Close();
}
private void lstMenuItems_SelectedIndexChanged(object sender, EventArgs e)
{
if (lstMenuItems.SelectedIndex > -1)
{
mnuitm = (MenuItem)lstMenuItems.SelectedItem;
}
}
}
After receiving feedback, I made the following changes:
Added CopyFrom() to MenuItem
public void CopyFrom(MenuItem itm)
{
this.ID = itm.ID;
this.URL = itm.URL;
this.Text = itm.Text;
this.Script = itm.Script;
}
I then modified the SelectedIndexChanged code to use the new function
mnuitm.CopyFrom((MenuItem)lstMenuItems.SelectedItem);
This is by design. When you write
itm = (MyItem)cboMyItemsCombobox.SelectedItem;
you haven't changed any of the properties of the MenuItem itm used to point to, rather you changed the MenuItem itm points to.
One option for what you need is add a function to MenuItem that looks like
SetFromOtherMenuItem(MenuItem other)
{
this.Url = other.Url
//etc
}
Again, PropertyChanged means that a property on some instance has changed. In your case, only one of the variables pointing to that instance changed (to point to a different instance).