How to update attribute value from object in a ListView - c#

I have two files. One file with a class called Wood. I have created some objects with this class. These Objects include the attribute WoodType and a few others. I filled the objects into an array called woodObjects. The second file is a Form where I have a ListView.
So my goal was, to add all objects with their attributes to the ListView. I did it like that:
String[] row = { (listView1.Items.Count + 1).ToString(), WoodType, condition, isDry};
ListViewItem item = new ListViewItem(row);
listView1.Items.Add(item);
Success.
Now I have to update the attribute WoodType of one object in the ListView. I created a button "change Type" for that. I thought of the user clicking the row where the object ist he wants to change, and then clicking the button "change Type" to change WoodType it.
To realize this, I wanted to take the index of the row, and than changing the value of "WoodType" with its set Accessor with something like the following:
woodObjects[indexOfRowFromListView].WoodType = "Oak Wood";
Yes, I know, this would never work like that. So my questions are: How can I select the correct index and how do I change the value of the attribute?
*I also thought of deleting the objects, but saving its values so I can create a new objects with the same values except WoodType.
I appreciate every help!

I think the cleanest solution to your problem would involve writing a new ListViewItem implementation. Something like this:
public class WoodObjectListItem : System.Windows.Forms.ListViewItem
{
public Wood WoodObject { get; }
public WoodObjectListItem(int rowNumber, Wood woodObject)
: base(new string[] { rowNumber.ToString(), woodObject.WoodType, woodObject.Condition, woodObject.IsDry })
{
WoodObject = woodObject;
}
public void ChangeType()
{
WoodObject.WoodType = "Oak Wood";
}
}
Then you could add your woodObjects to the list view like:
listView1.Items.Add(new WoodObjectListItem(listView1.Items.Count + 1, woodObject));
And when the button is clicked you could do:
if (listView1.SelectedItem is WoodObjectListItem woodObjectListItem)
woodObjectListItem.ChangeType();

Related

Updating ListBox With New COM Port Data

I wish for my ListBox to update the old values with new values rather than simply adding more and more lines to the ListBox like it does at the moment. However, I'm not sure where to look to implement something that can handle this.
My current code looks like this:
private void DisplayText(string rawData)
{
textArduinoData.Text = rawData;
string[] sortedData = rawData.Split(';');
for (int i = 0; i < sortedData.Length; i++)
{
listPortData.Items.Add(sortedData[i].ToString());
}
}
Could someone please point me in the right direction to implementing this update feature? Any advice would be much appreciated.
You need to manage the process. It is easy in concept but depending on how much data is needed to be processed, it could get slow quickly. Steps
Create a specialized token class which implements to INotifyPropertyChanged.
Have an ObservableCollection hold the class items from #1. The observable collection notifies the ListBox when an item is added or removed. This will allow your code to add items one at a time. (Solves 1 problem)
To solve the next problem of data changing: Have a property named Text, on the class in #1 which will hold the data, provide a property change notification.
In the list box bind to the list of items created in step 1 and specify to bind to the Text. Use of a data template for the listbox will allow you to bind to the Text property of the list's instance.
Provide the heuristics/ smarts to read incoming data and find the associated data in the observable collection from step 2. When found change the Text property of the existing data to the new and the binding of that list item will change accordingly.
You could check if the ListBox contains the string using the IndexOf method and then update the existing string (or simply do nothing) or add a new one depending on whether you get an index other than the default value of -1 back:
private void DisplayText(string rawData)
{
textArduinoData.Text = rawData;
string[] sortedData = rawData.Split(';');
int index;
for (int i = 0; i < sortedData.Length; i++)
{
if ((index = listPortData.Items.IndexOf(sortedData[i])) == -1)
{
listPortData.Items.Add(sortedData[i]);
}
}
}

How do I iterate through all the items in a listbox

So I have this listbox with the ItemSource of a ObservableCollection
And let's say I add 2 items to the listbox then the ObservableCollection contains 2 strings right?
Now.. I'm trying to create a messagebox popup containing whatevers in the string.
So let's say I have a listbox with 2 items, Cat & Bob.
Now when I press I button I want it to prompt me with two messageBoxes, one saying Cat & one saying bob.
I tried doing a foreach statement but it doesnt want to execute when I press the button.
Now.. The ObservableCollection is in 1 Window and the button I press is in another window so im not sure if that makes a difference.
So what I did is I declared the other window at the top of this one like so..
People peps = new People();
foreach(string email in peps.recipients)
{
if (comboBox1.Text == "Email")
{
MessageBox.Show(peps.Listbox1.Items.ToString());
MessageBox.Show(peps.Listbox1.Items.ToString());
}
}
But it's not printing out anything.
How do I make the messageboxes show whatever is in the Listbox1
Without actually seeing your People class, or a good many other things, and recklessly making assumptions as to what you're trying to accomplish, I'm going to assume that your People class looks something like this:
class People
{
public string m_sName {get; set; }
public string m_sEmail {get; set; }
public People(){}
public People(string name = null, string email = null)
{
m_sName = name;
m_sEmail = email;
}
Then after you've filled up your ListBox, you want to go through the contents, and display them in a MessageBox?....
List<people> lstPeeps = new List<people>();
foreach (var item in ListBox1.Items)
{
if (item.Contains("#")) //This checks to see if it's an email address...
lstPeeps.Add(item as peep.m_sEmail);
else lstPeeps.Add(item as peep.m_sName);
foreach (var peep in lstPeeps)
MessageBox.Show(peep.name + "\t" + peep.email);
Maybe something like that... If that doesn't work, give us a little more to work with and I'll modify the answer accordingly.

How to save CheckBoxRowSelect in Devexpress GridView to class object

I've simple class called "Order".
class Order {
public string ID { get;set;}
public string Something {get;set;}
.... more fields...
}
I then assign list of orders into DataSource of GridControl.
List <Order> ListOfOrders = new Order();
gridControl.DataSource = ListOfOrders;
I've added a CheckBoxRowSelect option in GUI so that user can choose rows by selecting the checkbox. What value do I need to add to class Order so that any checkbox change in that GridControl gets updated in instant in it's own field so that the ListOfOrders is always up to date and has that checkbox value stored so it can be processed?
I've made similar thing with ComboBox inside one of the columns and it seems to work instantly without any additional change on my part.
var columnKurier = view.Columns.AddField("Courier");
columnKurier.ColumnEdit = riCombo;
columnKurier.VisibleIndex = 0;
columnKurier.OptionsColumn.AllowFocus = true;
I simply had to add Courier field into Order class and that's it. But i don't know which "field name" should it be for checkbox and whether it will get the same behaviour as for the ComboBox.
Add in your object order :
public Boolean Mark{get;set;}
and in your your form contructor :
InitializeComponent();
new GridCheckMarksSelection(gridControl);
i have atach a class GridCheckMarksSelection you must add it in your project.
MarkClass
I hop that you want
You can not add the option CheckBoxRowSelect to GridControl, and just use a bool field in your Class Order, it should be displayed as checkbox in GridControl.

How can I add an item to a ListBox in C# and WinForms?

I'm having trouble figuring out how to add items to a ListBox in WinForms.
I have tried:
list.DisplayMember = "clan";
list.ValueMember = sifOsoba;
How can I add ValueMember to the list with an int value and some text for the DisplayMember?
list.Items.add(?)
Btw. I can't use ListBoxItem for any reasons.
ListBoxItem is a WPF class, NOT a WinForms class.
For WPF, use ListBoxItem.
For WinForms, the item is a Object type, so use one of these:
1. Provide your own ToString() method for the Object type.
2. Use databinding with DisplayMemeber and ValueMember (see Kelsey's answer)
list.Items.add(new ListBoxItem("name", "value"));
The internal (default) data structure of the ListBox is the ListBoxItem.
In WinForms, ValueMember and DisplayMember are used when data-binding the list. If you're not data-binding, then you can add any arbitrary object as a ListItem.
The catch to that is that, in order to display the item, ToString() will be called on it. Thus, it is highly recommended that you only add objects to the ListBox where calling ToString() will result in meaningful output.
You might want to checkout this SO question:
C# - WinForms - What is the proper way to load up a ListBox?
DisplayMember and ValueMember are mostly only useful if you're databinding to objects that have those properties defined. You would then need to add an instance of that object.
e.g.:
public class MyObject
{
public string clan { get; set; }
public int sifOsoba { get; set; }
public MyObject(string aClan, int aSif0soba)
{
this.clan = aClan;
this.sif0soba = aSif0soba;
}
public override string ToString() { return this.clan; }
}
....
list.Items.Add(new MyObject("hello", 5));
If you're binding it manually then you can use the example provided by goggles
The way I do this - using the format Event
MyClass c = new MyClass();
listBox1.Items.Add(c);
private void listBox1_Format(object sender, ListControlConvertEventArgs e)
{
if(e.ListItem is MyClass)
{
e.Value = ((MyClass)e.ListItem).ToString();
}
else
{
e.Value = "Unknown item added";
}
}
e.Value being the Display Text
Then you can attempt to cast the SelectedItem to MyClass to get access to anything you had in there.
Also note, you can use anything (that inherits from object anyway(which is pretty much everything)) in the Items Collection.
If you just want to add a string to it, the simple answer is:
ListBox.Items.Add("some text");
You have to create an item of type ListBoxItem and add that to the Items collection:
list.Items.add( new ListBoxItem("clan", "sifOsoba"));
If you are adding integers, as you say in your question, this will add 50 (from 1 to 50):
for (int x = 1; x <= 50; x++)
{
list.Items.Add(x);
}
You do not need to set DisplayMember and ValueMember unless you are adding objects that have specific properties that you want to display to the user. In your example:
listbox1.Items.Add(new { clan = "Foo", sifOsoba = 1234 });

WPF: SelectedItems with duplicate object references

So lets say I have these classes:
public class Person
{
public string Name { get; set; }
}
public class PersonCollection : ObservableCollection<Person> { }
And lets say I have a ListView whose ItemsSource is bound to a PersonCollection. Now lets say I have this code:
public void AddPeople()
{
Person p = new Person() { Name = "Someone" };
MyPersonCollection.Add(p);
MyPersonCollection.Add(p);
MyPersonCollection.Add(p);
}
So now I have a ListView with three items in which all three items are references to the SAME object. So now I select lets say items with index 0 and 2 in the ListView.
The ListView.SelectedItems property will say I have ONE item selected since both visually selected items are the SAME object.
So how can I get the visually selected items so I can remove the items at indices 0 and 2, without removing the item at index 1?
In WinForms there is the ListBox.SelectedIndices property that would be useful here, but we don't have that in WPF, unfortunately...
You could iterate through the ListViewItems using ItemContainerGenerator.ContainerFromIndex, check ListViewItem.IsSelected and then remove them by index. However, this doesn't play well with virtualization because ContainerFromIndex could return null if you scroll away from the item and it gets virtualized.
The code would look something like this:
for(int ixPerson = myListView.Items.Count - 1; ixPerson >= 0; ixPerson--)
{
ListViewItem personItem = myListView.ItemContainerGenerator.ContainerFromIndex(ixPerson);
if (personItem.IsSelected)
{
mySourcePersonCollection.RemoveAt(ixPerson);
}
}
There are cases where this makes sense, adding people to a queue where appearing more than once is desirable for instance. For this case it seems like WPF is designed poorly. Is it possible to manually iterate between all items in the collection and check their selection state?
I think there's something wrong with your model! Whatever it is you are trying to achieve, I would try and find a more robust way of doing it.

Categories

Resources