i tried to remove item from listbox using MultiExtended as selection mode
this is my code
im using this snippet code for getid from listbox
private int getid(int index)
{
int.TryParse(lb_ItemList.Items[lb_ItemList.SelectedIndices[index]].ToString().Split('-')[0], out index);
return index;
}
and this code im using for remove index from listbox
for (int i = lb_ItemList.Items.Count - 1; i > -1; i--)
{
lb_ItemList.Items.RemoveAt(lb_ItemList.SelectedIndices[getid(i)]);
}
but for any reason it doesn't work... any suggestion? thanks
I assume you need to copy the content of lb_ItemList.SelectedIndices before you start remove items out of lb_ItemList because every call to Remove(...) will update the content of lb_ItemList.SelectedIndices
You only need remove by index and SelectedIndices has the index:
for (int i = lb_ItemList.SelectedIndices.Count - 1; i > -1; i--)
{
var index = lb_ItemList.SelectedIndices[i];
lb_ItemList.Items.RemoveAt(index);
}
You don't need your Id to remove selected items.
If you need work with you class in the Items, I recomended you create an Item class:
public class YourItem
{
public YourItem()
{
}
public YourItem(int id, string name)
{
this.Id = id;
this.Name = name;
}
public int Id { get; set; }
public string Name { get; set; }
public override string ToString()
{
return $"{this.Id} - {this.Name}";
}
}
Then, you add your items to the ListBox:
this.lb_ItemList.Items.Add(new YourItem(1, "A"));
this.lb_ItemList.Items.Add(new YourItem(2, "B"));
this.lb_ItemList.Items.Add(new YourItem(3, "C"));
this.lb_ItemList.Items.Add(new YourItem(4, "D"));
The text of each item is that you return in ToString method of YourItem. For example "1 - A" for the first item.
And, when you are working with the ListBox, simply cast to your class:
var item = (YourItem)this.lb_ItemList.Items[1];
var id = item.Id;
var name = item.Name;
If you class is big, you can use your Item as a wrapper:
public class YourClass
{
public int Id { get; set; }
public string Name { get; set; }
// Other properties, methods...
}
public class YourItem
{
private YourClass _item;
public YourItem(YourClass obj)
{
this._item = obj;
}
public int Id
{
get { return this._item.Id}
set { this._item.Id = value; }
}
public string Name
{
get { return this._item.Name}
set { this._item.Name = value; }
}
public override string ToString()
{
return $"{this.Id} - {this.Name}";
}
}
Your class maybe have lost of information but for your item, you only expose Id and Name, for example.
Related
I would like to set a property called "Current" which give me the opportunity to keep track of which item I'm working with. Here's my class Volume:
namespace ConsoleApp3 {
class Volume : Interface
{
public string Name { get; set; }
public Volume()
{
}
}
My interface called: "Interface"
namespace ConsoleApp3{
class Interface
{
public string Name { get; set; }
public int Id { get; set; }
public bool IsCurrent { get; set; }
}
And my RootList Class:
namespace ConsoleApp3{
class RootList<T> : List<T> where T : Interface, new()
{
private int _index;
private int _id;
public RootList()
{
}
public T First
{
get => this[0];
set => this[0] = value;
}
public T Last
{
get => this[this.Count - 1];
set => this[this.Count - 1] = value;
}
public T Current
{
get
{
return this.FirstOrDefault(tTemp => tTemp.IsCurrent == true);
}
set
{
this.RmCurrent();
int _index = this.IndexOf(value);
this[_index].IsCurrent = true;
}
}
public T this[string name]
{
get
{
return this.FirstOrDefault(tTemp => tTemp.Name == name);
}
}
private void RmCurrent()
{
var _iscurrent = this.Where(v => v.IsCurrent = true);
foreach (var item in _iscurrent)
{
item.IsCurrent = false;
}
}
public void Add()
{
this.Add(new T());
this.RmCurrent();
this.Last.IsCurrent = true;
}
}
}
I'm using the "IsCurrent" property to track my items: my item has the "Current" state if the "IsCurrent" property is "true". Only one item can me the "Current" one at the same time.
My "Current" method doesn't work. For exmaple:
VolumeList.Add();
VolumeList.Last.Name = "test_0";
VolumeList.Add();
VolumeList.Last.Name = "test_1";
VolumeList.Add();
VolumeList.Last.Name = "test_2";
In this case, my Current item is the Last one "test_2".
If I do that:
VolumeList.Current = VolumeList[1];
I have two Current items VolumeList[0] and VolumeList[1]. Not only VolumeList[1].
As you can see, I also have a string indexer in my RootList so it has to work with int indexer and string indexer.
Do you have any ideas?
Thanks a lot.
Best regards,
I would not search for an item which is current in private void RmCurrent()
I would only do
private void RmCurrent()
{
foreach (var item in this)
{
item.IsCurrent = false;
}
}
I'd make the RootList track current:
public class RootList<T> : List<T> where T : Interface, new()
{
public T Current { get; private set; }
public T First
{
get => Current = this[0];
set => Current = this[0] = value;
}
public T Last
{
get => Current = this[this.Count - 1];
set => Current = this[this.Count - 1] = value;
}
public T this[string name]
{
//what if there is no such name? what do you want current to be?
//if it should not change, break this lambda up using a temp var
//that you do not assign to current if it is null
get => Current = this.FirstOrDefault(tTemp => tTemp.Name == name);
}
public void Add() //careful, the List<T> you inherit from also has an Add(T), and so calling myList.Add(something) it won't set the current item
{
Current = new T();
this.Add(Current);
}
}
So what's going on ?
Assignments in C# return, as a value, the value that was assigned. It means that this:
myString = "hello";
returns "hello". It can be used in another assignment:
myString2 = (myString = "hello");
Both the strings are "hello";
Single line lambdas must be a value, so this:
get => Current = this[0];
Assigns the Current to be the first item in the list and then gives the first item in the list to the get, to be returned. It's like saying:
get {
Current = this[0];
return Current;
}
Your Current is now the first item in the list, just because you accessed the First property
I use this code to move between instances of a class
public class Orders : List<Order>
{
int currentIndex = 0;
public int CurrentIndex {
get {
if (currentIndex == Count) {
currentIndex = 0;
} else if (currentIndex > Count - 1) {
currentIndex = Count - 1;
} else if (currentIndex < 0) {
currentIndex = 0;
}
return currentIndex;
}
set { currentIndex = value; }
}
public void MoveNext()
{
currentIndex++;
}
public void MovePrevious()
{
currentIndex--;
}
public Order Current {
get {
return this[CurrentIndex];
}
}
}
public class Cart
{
public string id_ordine { get; set; }
public string nome { get; set; }
public string cognome { get; set; }
public double prezzo { get; set; }
}
but I can't figure out hot to make the same with complex class that includes a list like in following case.
I have tried it in many way..
public class Order
{
public string nome { get; set; }
public string cognome { get; set; }
public List<OrdersList> ordersList { get; set; }
}
public class OrdersList
{
public string id_ordine { get; set; }
public double prezzo { get; set; }
}
to be more specific considider that i have one order that contain more order list
for example
order orderslist
-------------+-----------------
name surname id_ordine prezzo
-------------+-----------------
john doe --> 1 10
--> 2 12
--> 3 22
I would take a different approach entirely. A list of items doesn't naturally have a "cursor" in it - it's entirely logical to be able to have multiple cursors, like multiple bookmarks in a book.
I would stick to a List<OrdersList> for the list itself, but create an IndexedListEnumerator<T> type or something similar, with a GetIndexedEnumerator() extension method (probably on IList<T>). That would implement IEnumerator<T>, but also have a MovePrevious() method and an Index property.
That separates out the concern for "I want to have a more flexible cursor" from the concern of "I want a list of orders".
I'd also strongly recommend that unless you really, really need the sort of "wrap-around" functionality you currently have, that you make the index a simple property, but make Current throw an exception when trying to access an invalid index. (So the initial index would be -1, and Current would be invalid. Calling MoveNext() would take you to index 0 which would be valid for any non-empty list, etc.) As a rough sketch:
public static class ListExtensions
{
public static IndexedListEnumerator<T> GetIndexedListEnumerator<T>(this IList<T> list) =>
new IndexedListEnumerator<T>(list);
}
public sealed class IndexedListEnumerator<T> : IEnumerator<T>
{
private readonly IList<T> list;
// You *could* restrict this to the range [-1, list.Count] if you wanted.
public int Index { get; set; }
// You might want to make this public
private bool IndexIsValid => Index >= 0 && Index < list.Count;
public IndexedListEnumerator(IList<T> list)
{
this.list = list;
Index = -1; // Before the first element
}
// TODO: Consider using checked to throw an exception around int.MaxValue
public bool MoveNext()
{
Index++;
return IndexIsValid;
}
public bool MovePrevious()
{
Index--;
return IndexIsValid;
}
public T Current => list[Index];
object IEnumerator.Current => Current;
void IDisposable.Dispose() {}
void IEnumerator.Reset() => Index = -1;
}
Example usage, although you'd normally want to check the result of MovePrevious() and MoveNext():
List<Order> orders = ...;
var enumerator = orders.GetIndexedListEnumerator();
enumerator.Index = 10;
Console.WriteLine(enumerator.Current); // Prints orders[10]
enumerator.MovePrevious();
Console.WriteLine(enumerator.Current); // Prints orders[9]
enumerator.MoveNext();
enumerator.MoveNext();
Console.WriteLine(enumerator.Current); // Prints orders[11]
I have this class:
public class Test
{
public string Id { get; set; }
public int Number { get; set; }
public int DoubleNumber { get; set; }
}
and a list
List<Test> myTestList;
How can I make the value of the field DoubleNumber in myTestList equal to twice the value of Number? Note that I am okay to create another list if that's needed.
If I understand your question correctly:
foreach(Test item in myList) {
item.DoubleNumber = 2*item.Number;
}
Or, if it's ok, just remove the setter and modify the getter to return 2x Number:
public class Test
{
public string Id { get; set; }
public int Number { get; set; }
public int DoubleNumber { get { return 2* this.Number; } } //completely remove setter
}
Or, if you still want to be able to modify DoubleNumber:
public class Test {
private int m_num;
private int m_doubleNum;
public string Id {
get;
set;
}
public int Number {
get {
return this.m_num;
}
set {
this.m_num = value;
this.m_doubleNum = 2 * value; //when Number is set, update m_doubleNum too
}
}
public int DoubleNumber {
get {
return this.m_doubleNum;
}
set {
this.m_doubleNum = value; //allow manual setting of DoubleNumber
//or maybe also modify Number here?
//this.m_num = value / 2;
}
}
}
One way it could be using a foreach statement:
foreach(var item in myTestList)
{
item.DoubleNumber = 2*item.Number;
}
Another way it could be to use LINQ.
var result = myTestList.Select(test => new Test
{
test.Id,
test.Number,
DoubleNumber = 2*test.Number;
})
.ToList();
Among the two ways I would prefer the first one, since it's more clear what you are trying to do and more performant (in the second approach you have to create a new object for each object in myTestList).
I've this combobox:
<ComboBox x:Name="notification_mode" ItemsSource="{Binding NotificationMode}"
DisplayMemberPath="Text"/>
in my model I've created a class that add also the value to comboboxitem:
public class ComboboxItem
{
public string Text { get; set; }
public object Value { get; set; }
public override string ToString()
{
return Text;
}
}
so in my viewmodel I've created an observableCollection that store all the items:
private ObservableCollection<Models.ComboboxItem> _notificationMode = new ObservableCollection<Models.ComboboxItem>();
public ObservableCollection<Models.ComboboxItem> NotificationMode
{
get
{
return _notificationMode;
}
set
{
Models.ComboboxItem item = new Models.ComboboxItem();
item.Text = "Con sonoro";
item.Value = 0;
_notificationMode.Add(item);
}
}
The problem's that in the combobox item isn't displayed nothing. Why happen this?
This is the standard Property declaration
public ObservableCollection<Models.ComboboxItem> NotificationMode
{
get
{
return _notificationMode;
}
set
{
_notificationMode = value;
OnPropertyChanged("NotificationMode");
}
}
You can initialize the above defined property in the ViewModel constructor
public YourViewModel()
{
Models.ComboboxItem item = new Models.ComboboxItem();
item.Text = "Con sonoro";
item.Value = 0;
_notificationMode.Add(item);
}
I have a problem, if i want to edit a value into an object and call it again, i get the old value instead of the new one.
Here is my Function to get the Class:
public static Clan GetClanByID(int Index)
{
foreach (Clan Clan in Clans)
{
if (Clan.ID == Index)
{
return Clan;
}
}
return new Clan()
{
ID = -1,
Name = "NULL",
IconID = -1
};
}
Here is my function to update the Value:
public static void ChangeAnnouncement(int ClanID, int Mode, string Text)
{
if (ClanID != -1)
{
Clan Clan = GetClanByID(ClanID);
if (Mode == 0)
{
Clan.Description = Text;
}
else if (Mode == 1)
{
Clan.News = Text;
}
}
}
And here is the class:
public class Clan
{
public int ID;
public int LeaderID;
public int Extension;
public int CreationDate;
public long EXP;
public long IconID;
public string Name;
public string News;
public string Description;
public List<ClanWars> ClanWars;
public List<ClanUsers> Users;
public List<ClanCoMasters> CoMasters;
public List<ClanPendingUsers> PendingUsers;
public LeaderInformations LeaderInformations;
}
Example: The old value was "123", than i call the function ChangeAnnouncement, and set the value to "1234567890", after that i get the value using GetClanByID(ID).Description, but i will still get the old value ("123")
I Hope you can help me.
You're returning a new Clan every time. You forgot adding the newly created clan to Clans.