Issue with populating a listbox with an already existing array - c#

struct process
{
public int Proc_Id;
public int Proc_BurstTime;
public int Proc_Priority;
};
readonly process[] ProcessList = new process[]
{
new process{ Proc_Id = 1, Proc_BurstTime = 3000, Proc_Priority = 1},
new process{ Proc_Id = 2, Proc_BurstTime = 5000, Proc_Priority = 2},
new process{ Proc_Id = 3, Proc_BurstTime = 1000, Proc_Priority = 3},
new process{ Proc_Id = 4, Proc_BurstTime = 10000, Proc_Priority = 4}
};
private void Form1_Load(object sender, EventArgs e)
{
initial_ProcessList.Items.AddRange(ProcessList);
}
This is the error I get:
The best overloaded method match for 'System.Windows.Forms.ListBox.ObjectCollection.AddRange(System.Windows.Forms.ListBox.ObjectCollection)' has some invalid arguments
Argument 1: cannot convert from 'OS450_Proj1.Form1.process[]' to 'System.Windows.Forms.ListBox.ObjectCollection'
I understand that it looks like it doesn't like that kind of array, but is there anything can do to populate the listbox? If it is also because there's no string or anything to "print" onto the list, do I need to add a string value to the struct and initialize it for all the values in the array (ProcessList)? If so, how can I go about that when adding to the listbox?

Yes, you can't cast somearray to object[]. ListBox.Items.AddRange requires object array to be passed as parameter.
Try this
initial_ProcessList.Items.AddRange(ProcessList.Cast<object>().ToArray());
or this
object[] ProcessList = new object[]
{
new process{ Proc_Id = 1, Proc_BurstTime = 3000, Proc_Priority = 1},
new process{ Proc_Id = 2, Proc_BurstTime = 5000, Proc_Priority = 2},
new process{ Proc_Id = 3, Proc_BurstTime = 1000, Proc_Priority = 3},
new process{ Proc_Id = 4, Proc_BurstTime = 10000, Proc_Priority = 4}
};
Or just loop and add
foreach (var p in ProcessList)
{
initial_ProcessList.Items.Add(p);
}

First the error, If the method is expecting a object[] it can't take a process[] for that. Now if you try something like:
initial_ProcessList.Items.AddRange(ProcessList.Cast<object>().ToArray());
The error would go away but the ListBox items would appear like:
WindowForm.ApplicationName.process1
WindowForm.ApplicationName.process1
.....
Which is the default ToString() implementation. So your actual problem is displaying those records in the ListBox. You have to override ToString method. like:
struct process
{
public int Proc_Id;
public int Proc_BurstTime;
public int Proc_Priority;
public override string ToString()
{
return string.Format("{0}, {1}, {2}", Proc_Id, Proc_BurstTime, Proc_Priority);
}
};
Later it would even more simpler if use the DataSource Property instead of adding an object array so simply do:
initial_ProcessList.DataSource = ProcessList;
This would show the result as:
You can also set DisplayMember and ValueMember property of your ListBox but it would require your structure to have properties, instead of fields. So you have to modify your struct as:
struct process
{
public int Proc_Id { get; set; }
public int Proc_BurstTime { get; set; } //auto implemented properties
public int Proc_Priority;
};
And then:
initial_ProcessList.ValueMember = "Proc_Id";
initial_ProcessList.DisplayMember = "Proc_BurstTime";
initial_ProcessList.DataSource = ProcessList;
This would show only Proc_BurstTime, and on selection you will get the value of related Proc_Id

Related

I want to create multiple objects in list<object> and remove them with the desired id

I want to delete it with the desired id.
Can you tell me if there is another way to do it with Linq?
I think I can use Select() and Where(), but it doesn't work.
var list = new List<object>() { };
list.Add(new { id = 3, const = "22"});
list.Add(new { id = 4, const = "22"});
list.Add(new { id = 6, const = "22"});
list.Add(new { id = 2, const = "22"});
list.Add(new { id = 1, const = "22"});
//example
list.Remove(new { id = 2, const = "22" });
first of all const is a keyword in C#, so either avoid using it as member name, or escape it by decorating with #.
since your list item type is object, you need to cast them as dynamic to allow access the 'unknown' id -> this a very vague approach, but it works.
= in C# means: set the value of... so if you want to compare equality, you need ==
putting this altogether:
var list = new List<object>();
list.Add(new { id = 4, #const = "22" });
list.Add(new { id = 4, #const = "22" });
list.Add(new { id = 6, #const = "22" });
list.Add(new { id = 2, #const = "22" });
list.Add(new { id = 1, #const = "22" });
list.RemoveAll(i => ((dynamic)i).id == 2);
will work.
Consider using an own Type for your list items, anonymous types should only be used 'locally' in Queries like GroupBy.
you could try:
list.RemoveAt(list.FindIndex(item => item.id == 1));

Find missing item in a list grouped

I have a list of objects dailySchedule with the properties Order, District, and other properties.
public class dailySchedule
{
public int Order { get; set; }
public string Title { get; }
public string District { get; }
....
}
the list is loaded with these values
Each district must have 6 orders,
var ordersValue = new List<int> {1, 2, 3, 4, 5, 6};
I want to find for each district, which order is missing.
The result must be
District 0 order {2,3,5,6}
District 12 order {5,6}
How can do that with linq c#?
This is a case for Except():
you can achieve your desired result by "substracting two lists" like so:
var required = new List<int>() {1, 2, 3, 4, 5, 6};
var groupedByDistrict = orders.GroupBy(x => x.District);
foreach (var group in groupedByDistrict)
{
var missing = required.Except(group.Select(x => x.Order).Distinct());
// Do something with that informaton here
}
This is mere non working pseudocode to get you on the right track
actually it may work, but i haven't tested it.
Try the below code which will give you result with each district and its missing orders
var allOrders = new List<int>() { 1, 2, 3, 4, 5, 6 };
var result = orders.GroupBy(gp => gp.District).Select(sl =>
new { District = sl.Key, Order = allOrders.Where(wh => sl.All(all => all.Order != wh)) });

c# loop through all fields of enum assigning values from string array

I am building a Soap Body for a web-service, and there are dozens of optional fields.
Currently I have been handling these like this:
wsSoapBody.OrderType = aMessage[(int)cardCreate.OrderType].ToString();
wsSoapBody.ActivateFlag = Convert.ToInt32(aMessage[(int)cardCreate.ActivateFlag].ToString()); //P-02925;
if (aMessage[(int)cardCreate.ShipDate].ToString() != ""){
wsSoapBody.ShipmentDate = Convert.ToDateTime(aMessage[(int)cardCreate.ShipDate].ToString()); //P-02925;
}
wsSoapBody.ShipmentMethodCard = aMessage[(int)cardCreate.ShipMethodCard].ToString();
wsSoapBody.ShipmentMethodPin = aMessage[(int)cardCreate.ShipMethodPIN].ToString();
The CardCreate you see in those value assignments is an enumerated constant in the class cardCreate defined as below:
namespace EvryCardManagement
{
class CardCreate
{
#region Variables
private DCSSCardCreateType req;
private DCSSCardCreateResponseType rsp;
private DCSSCardCreate_V3_0Service stub;
public string tokenID { get; set; }
private enum cardCreate
{
MsgType = 0,
MsgVersion = 1,
WSName = 2,
ReplyTo = 3,
SourceSystem = 4,
Timestamp = 5,
UniqueMessageID = 6,
SFDCContext = 7,
InstitutionID = 8,
CardNumber = 9,
Version = 10,
ProductID = 11,
AccountNumber = 12,
CustomerID = 13,
CustomerNumber = 14,
EmbossName1 = 15,
Expiry = 16,
FeeMonth = 17,
ChargeAccountNo = 18,
PINMethod = 19,
CardFlag = 20,
AddressTypeCard = 21,
AddressTypePIN = 22,
OrderType = 23,
ActivateFlag = 24,
ShipDate = 25,
ShipMethodCard = 26,
ShipMethodPIN = 27,
FirstName = 28,
LastName = 29,
CardAddress1 = 30,
CardAddress2 = 31,
CardAddress3 = 32,
CardAddress4 = 33,
CardAddress5 = 34,
CardAddress6 = 35,
CardPostCode = 36,
CardCity = 37,
CardCountry = 38,
PINName = 39,
PINAddress1 = 40,
PINAddress2 = 41,
PINAddress3 = 42,
PINAddress4 = 43,
PINAddress5 = 44,
PINAddress6 = 45,
PINPostCode = 46,
PINCity = 47,
PINCountry = 48,
Validfrom = 49,
Note = 50,
MakeCheckStatus = 51,
EmbossName2 = 52,
PAmount = 53,
PAmountLength = 54,
GKIndicator = 55,
CreditLimit = 56,
CardDesignNo = 57,
ExtPictureID = 58,
BulkID = 59,
AccountNo2 = 60
}
so, rather than doing them all one by one as I have been doing, is it possible to loop through the wsSoapBody (which is defined in the web-service) and for each one, get the corresponding value from the aMessage (which is defined as an array like this string[] aMessage)
EDIT
I have the below code to loop through, but I want to assign to the wsSoapBody and I am stuck:
foreach (cardCreate cItem in (cardCreate[])Enum.GetValues(typeof(cardCreate)))
{
}
(the above correction was suggested as an edit by Steve Lillis that was rejected due to a conflict)
so I don't know how then to assign the values to each element for example I want to set
wsSoapBody[cItem].value = aMessage[(int)CardCreate[cItem]`
or I also tried:
wsSoapBody[cItem] = aMessage[(int)cItem].ToString();
but am having trouble making it work (or even compile) due to lack of knowledge
EDIT #2:
I have also looked at GetNames as possibly I want the names and tried:
foreach (string name in Enum.GetNames(typeof(cardCreate)))
{
wsSoapBody[name] = aMessage[(int)name].ToString();
}
But I cannot apply indexing with [] to an expression of type 'DCSSCardCreateType'
thanks
Why not place the values onto the enum itself and then enumerate?
For example using System.ComponentModel Description attribute we can add that information to the enum itself such as:
public enum cardCreate
{
[Description("General Response")]
MsgType = 0,
[Description("V2.0")]
WSName = 2,
[Description("OmegaMan")]
ReplyTo = 3,
[Description("Windows 10")]
SourceSystem = 4,
}
So when we call a special method to enumerate the enum where we can extract that text and use it appropriately later such as:
myextensions.GetEnumValues<cardCreate>()
.Select (ceEnum => new
{
Original = ceEnum,
IndexValue = (int)ceEnum,
Text = ceEnum.GetAttributeDescription()
})
The dynamic entity will look like this after the projection (the select):
Sweet! Now we have all the information in a easy consumable entity which provides all the information needed.
What? You need more than a string description? Then create a custom attribute on the enum and have all items/types of data to return as needed. For that see my blog article C# Using Extended Attribute Information on Objects.
Here are the extension methods used in the above example:
public static class myextensions
{
public static IEnumerable<T> GetEnumValues<T>()
{
Type type = typeof( T );
if (!type.IsEnum)
throw new Exception( string.Format("{0} is not an enum.", type.FullName ));
FieldInfo[] fields =
type.GetFields( BindingFlags.Public | BindingFlags.Static );
foreach (var item in fields)
yield return (T)item.GetValue( null );
}
/// <summary>If an attribute on an enumeration exists, this will return that
/// information</summary>
/// <param name="value">The object which has the attribute.</param>
/// <returns>The description string of the attribute or string.empty</returns>
public static string GetAttributeDescription( this object value )
{
string retVal = string.Empty;
try
{
retVal = value.GetType()
.GetField( value.ToString() )
.GetCustomAttributes( typeof( DescriptionAttribute ), false )
.OfType<DescriptionAttribute>()
.First()
.Description;
}
catch (NullReferenceException)
{
//Occurs when we attempt to get description of an enum value that does not exist
}
finally
{
if (string.IsNullOrEmpty( retVal ))
retVal = "Unknown";
}
return retVal;
}
}

How to easily initialize a list of Tuples?

I love tuples. They allow you to quickly group relevant information together without having to write a struct or class for it. This is very useful while refactoring very localized code.
Initializing a list of them however seems a bit redundant.
var tupleList = new List<Tuple<int, string>>
{
Tuple.Create( 1, "cow" ),
Tuple.Create( 5, "chickens" ),
Tuple.Create( 1, "airplane" )
};
Isn't there a better way? I would love a solution along the lines of the Dictionary initializer.
Dictionary<int, string> students = new Dictionary<int, string>()
{
{ 111, "bleh" },
{ 112, "bloeh" },
{ 113, "blah" }
};
Can't we use a similar syntax?
c# 7.0 lets you do this:
var tupleList = new List<(int, string)>
{
(1, "cow"),
(5, "chickens"),
(1, "airplane")
};
If you don't need a List, but just an array, you can do:
var tupleList = new(int, string)[]
{
(1, "cow"),
(5, "chickens"),
(1, "airplane")
};
And if you don't like "Item1" and "Item2", you can do:
var tupleList = new List<(int Index, string Name)>
{
(1, "cow"),
(5, "chickens"),
(1, "airplane")
};
or for an array:
var tupleList = new (int Index, string Name)[]
{
(1, "cow"),
(5, "chickens"),
(1, "airplane")
};
which lets you do: tupleList[0].Index and tupleList[0].Name
Framework 4.6.2 and below
You must install System.ValueTuple from the Nuget Package Manager.
Framework 4.7 and above
It is built into the framework. Do not install System.ValueTuple. In fact, remove it and delete it from the bin directory.
note: In real life, I wouldn't be able to choose between cow, chickens or airplane. I would be really torn.
Yes! This is possible.
The { } syntax of the collection initializer works on any IEnumerable
type which has an Add method with the correct amount of arguments.
Without bothering how that works under the covers, that means you can
simply extend from List<T>, add a custom Add method to initialize your
T, and you are done!
public class TupleList<T1, T2> : List<Tuple<T1, T2>>
{
public void Add( T1 item, T2 item2 )
{
Add( new Tuple<T1, T2>( item, item2 ) );
}
}
This allows you to do the following:
var groceryList = new TupleList<int, string>
{
{ 1, "kiwi" },
{ 5, "apples" },
{ 3, "potatoes" },
{ 1, "tomato" }
};
C# 6 adds a new feature just for this: extension Add methods. This has always been possible for VB.net but is now available in C#.
Now you don't have to add Add() methods to your classes directly, you can implement them as extension methods. When extending any enumerable type with an Add() method, you'll be able to use it in collection initializer expressions. So you don't have to derive from lists explicitly anymore (as mentioned in another answer), you can simply extend it.
public static class TupleListExtensions
{
public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list,
T1 item1, T2 item2)
{
list.Add(Tuple.Create(item1, item2));
}
public static void Add<T1, T2, T3>(this IList<Tuple<T1, T2, T3>> list,
T1 item1, T2 item2, T3 item3)
{
list.Add(Tuple.Create(item1, item2, item3));
}
// and so on...
}
This will allow you to do this on any class that implements IList<>:
var numbers = new List<Tuple<int, string>>
{
{ 1, "one" },
{ 2, "two" },
{ 3, "three" },
{ 4, "four" },
{ 5, "five" },
};
var points = new ObservableCollection<Tuple<double, double, double>>
{
{ 0, 0, 0 },
{ 1, 2, 3 },
{ -4, -2, 42 },
};
Of course you're not restricted to extending collections of tuples, it can be for collections of any specific type you want the special syntax for.
public static class BigIntegerListExtensions
{
public static void Add(this IList<BigInteger> list,
params byte[] value)
{
list.Add(new BigInteger(value));
}
public static void Add(this IList<BigInteger> list,
string value)
{
list.Add(BigInteger.Parse(value));
}
}
var bigNumbers = new List<BigInteger>
{
new BigInteger(1), // constructor BigInteger(int)
2222222222L, // implicit operator BigInteger(long)
3333333333UL, // implicit operator BigInteger(ulong)
{ 4, 4, 4, 4, 4, 4, 4, 4 }, // extension Add(byte[])
"55555555555555555555555555555555555555", // extension Add(string)
};
C# 7 will be adding in support for tuples built into the language, though they will be of a different type (System.ValueTuple instead). So to it would be good to add overloads for value tuples so you have the option to use them as well. Unfortunately, there are no implicit conversions defined between the two.
public static class ValueTupleListExtensions
{
public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list,
ValueTuple<T1, T2> item) => list.Add(item.ToTuple());
}
This way the list initialization will look even nicer.
var points = new List<Tuple<int, int, int>>
{
(0, 0, 0),
(1, 2, 3),
(-1, 12, -73),
};
But instead of going through all this trouble, it might just be better to switch to using ValueTuple exclusively.
var points = new List<(int, int, int)>
{
(0, 0, 0),
(1, 2, 3),
(-1, 12, -73),
};
You can do this by calling the constructor each time with is slightly better
var tupleList = new List<Tuple<int, string>>
{
new Tuple<int, string>(1, "cow" ),
new Tuple<int, string>( 5, "chickens" ),
new Tuple<int, string>( 1, "airplane" )
};
Old question, but this is what I typically do to make things a bit more readable:
Func<int, string, Tuple<int, string>> tc = Tuple.Create;
var tupleList = new List<Tuple<int, string>>
{
tc( 1, "cow" ),
tc( 5, "chickens" ),
tc( 1, "airplane" )
};
Super Duper Old I know but I would add my piece on using Linq and continuation lambdas on methods with using C# 7. I try to use named tuples as replacements for DTOs and anonymous projections when reused in a class. Yes for mocking and testing you still need classes but doing things inline and passing around in a class is nice to have this newer option IMHO. You can instantiate them from
Direct Instantiation
var items = new List<(int Id, string Name)> { (1, "Me"), (2, "You")};
Off of an existing collection, and now you can return well typed tuples similar to how anonymous projections used to be done.
public class Hold
{
public int Id { get; set; }
public string Name { get; set; }
}
//In some method or main console app:
var holds = new List<Hold> { new Hold { Id = 1, Name = "Me" }, new Hold { Id = 2, Name = "You" } };
var anonymousProjections = holds.Select(x => new { SomeNewId = x.Id, SomeNewName = x.Name });
var namedTuples = holds.Select(x => (TupleId: x.Id, TupleName: x.Name));
Reuse the tuples later with grouping methods or use a method to construct them inline in other logic:
//Assuming holder class above making 'holds' object
public (int Id, string Name) ReturnNamedTuple(int id, string name) => (id, name);
public static List<(int Id, string Name)> ReturnNamedTuplesFromHolder(List<Hold> holds) => holds.Select(x => (x.Id, x.Name)).ToList();
public static void DoSomethingWithNamedTuplesInput(List<(int id, string name)> inputs) => inputs.ForEach(x => Console.WriteLine($"Doing work with {x.id} for {x.name}"));
var namedTuples2 = holds.Select(x => ReturnNamedTuple(x.Id, x.Name));
var namedTuples3 = ReturnNamedTuplesFromHolder(holds);
DoSomethingWithNamedTuplesInput(namedTuples.ToList());
One technique I think is a little easier and that hasn't been mentioned before here:
var asdf = new [] {
(Age: 1, Name: "cow"),
(Age: 2, Name: "bird")
}.ToList();
I think that's a little cleaner than:
var asdf = new List<Tuple<int, string>> {
(Age: 1, Name: "cow"),
(Age: 2, Name: "bird")
};
var colors = new[]
{
new { value = Color.White, name = "White" },
new { value = Color.Silver, name = "Silver" },
new { value = Color.Gray, name = "Gray" },
new { value = Color.Black, name = "Black" },
new { value = Color.Red, name = "Red" },
new { value = Color.Maroon, name = "Maroon" },
new { value = Color.Yellow, name = "Yellow" },
new { value = Color.Olive, name = "Olive" },
new { value = Color.Lime, name = "Lime" },
new { value = Color.Green, name = "Green" },
new { value = Color.Aqua, name = "Aqua" },
new { value = Color.Teal, name = "Teal" },
new { value = Color.Blue, name = "Blue" },
new { value = Color.Navy, name = "Navy" },
new { value = Color.Pink, name = "Pink" },
new { value = Color.Fuchsia, name = "Fuchsia" },
new { value = Color.Purple, name = "Purple" }
};
foreach (var color in colors)
{
stackLayout.Children.Add(
new Label
{
Text = color.name,
TextColor = color.value,
});
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label))
}
this is a Tuple<Color, string>

C# - Creating array where the array value has multiple objects and each one has a value too

I have just recently been doing something in C#, i would like to know how to do something like this.
Array[0] =
Array['Value'] = 2344;
Array['LocationX'] = 0;
Array['LocationY'] = 0;
Array[1] =
Array['Value'] = 2312;
Array['LocationX'] = 2;
Array['LocationY'] = 1;
Array[2] =
Array['Value'] = 2334;
Array['LocationX'] = 4;
Array['LocationY'] = 3;
The data it self its not important, the thing is that i know how to do this in PHP. But in C# i don't, and I've tried some ways and no luck.
In PHP i could just do something like this:
$Array[0]->Value = 2344;
$Array[0]->LocationX = 0;
$Array[0]->LocationY = 0;
And those values would be added to the Array.
In C# i've tried this and doesn't work that way.
Could someone enlighten me in how to do this in C#?
Thanks.
Well, you could have an array of instances of a class that you write like so:
public class DataForArray
{
public int Value { get; set; }
public int LocationX { get; set; }
public int LocationY { get; set; }
}
Then something like this:
DataForArray[] array = new DataForArray[10];
array[0] = new DataForArray();
array[0].Value = 2344;
etc...
Either write a class or struct to hold Value, LocationX and LocationY.
struct Foo
{
Foo(value, x, y)
{
Value = value;
LocationX = x;
LocationY = y;
}
Foo() {}
int Value;
int LocationX;
int LocationY;
}
Foo[] f = new []
{
new Foo(1, 2, 3),
new Foo(2, 3, 4)
}
or alternatively initialize the array this way:
Foo[] f = new []
{
new Foo() { Value = 1, LocationX = 2, LocationY = 3 },
new Foo() { Value = 4, LocationX = 5, LocationY = 6 },
}
Or use an Array of Dictionary<string, int>.
Dictionary<string, int>[] array = new []
{
new Dictionary<string, int>() {{ "Value", 1 }, {"LocationX", 2}, {"LocationY", 3 }},
new Dictionary<string, int>() {{ "Value", 4 }, {"LocationX", 5}, {"LocationY", 6 }}
}
Which is only recommended if it needs to be dynamic (means: you want to have different values in each element of the array or your keys are in strings, not known at compile-time.) Unless it is just hard to maintain.
in C#, you can try something like this
// initialize array
var list = new[]
{
new {Value = 2344, LocationX = 0, LocationY = 0},
new {Value = 2312, LocationX = 2, LocationY = 4},
new {Value = 2323, LocationX = 3, LocationY = 1}
}.ToList();
// iterate over array
foreach (var node in list)
{
var theValue = node.Value;
var thePosition = new Point(node.LocationX, node.LocationY);
}
// iterate over array with filtering ( value > 2300 )
foreach (var node in list.Where(el => el.Value > 2300))
{
var theValue = node.Value;
var thePosition = new Point(node.LocationX, node.LocationY);
}
// add again
list.Add(new { Value = 2399, LocationX = 9, LocationY = 9 });
Here is a link that details the use of Multidimensional arrays
http://msdn.microsoft.com/en-us/library/aa288453(VS.71).aspx
You can use anonymous type in C# like that:
var arr = new[] {
new{Value = 1, LocationX = 2, LocationY = 3},
new{Value = 1, LocationX = 2, LocationY = 3},
new{Value = 1, LocationX = 2, LocationY = 3},
new{Value = 1, LocationX = 2, LocationY = 3},
new{Value = 1, LocationX = 2, LocationY = 3} };
Only one problem is that properties in anonymous type are read-only. So You can't do something like that:
arr[1].Value = 2

Categories

Resources