C# ComboBox string array with int - arrays

Well, the title is a bit confusing but I want to ask if it possible to have a array with string and int inside ?
For example:
string[] versions = new string[] { "Normal",1, "Expert",2, "Pro",3 };
comboBox.Items.AddRange(versions);
So if I would select Normal, the version integer would be set to 1. In my programm I got alot if items in my comboBox, and I don't want to have 50+ if functions to set the integer.
Sorry for my bad english.

What you are looking for is an Object containing the string and int properties/fields. Try the following:
public class Version // You can replace "Version" with any name you'd like
{
public string Name { get; set; }
public int Value { get; set; }
}
Then you have an array of your Version-objects you can use:
Version[] versions = new Version[] {
new Version { Name = "Normal", Value = 1 },
new Version { Name = "Expert", Value = 2 },
new Version { Name = "Pro", Value = 3 }
};
I couldn't tell which programming language you are using (although I assumed .NET C# based on the code given).

Related

WPF ItemsControl doesnt update when I add a new item in ItemsSource [duplicate]

I've got a WCF service that passes around status updates via a struct like so:
[DataContract]
public struct StatusInfo
{
[DataMember] public int Total;
[DataMember] public string Authority;
}
...
public StatusInfo GetStatus() { ... }
I expose a property in a ViewModel like this:
public class ServiceViewModel : ViewModel
{
public StatusInfo CurrentStatus
{
get{ return _currentStatus; }
set
{
_currentStatus = value;
OnPropertyChanged( () => CurrentStatus );
}
}
}
And XAML like so:
<TextBox Text="{Binding CurrentStatus.Total}" />
When I run the app I see errors in the output window indicating that the Total property cannot be found. I checked and double checked and I typed it correctly. The it occurred to me that the errors specifically indicate that the 'property' cannot be found. So adding a property to the struct made it work just fine. But this seems odd to me that WPF can't handle one-way binding to fields. Syntactically you access them the same in code and it seem silly to have to create a custom view model just for the StatusInfo struct. Have I missed something about WPF binding? Can you bind to a field or is property binding the only way?
Binding generally doesn't work to fields. Most binding is based, in part, on the ComponentModel PropertyDescriptor model, which (by default) works on properties. This enables notifications, validation, etc (none of which works with fields).
For more reasons than I can go into, public fields are a bad idea. They should be properties, fact. Likewise, mutable structs are a very bad idea. Not least, it protects against unexpected data loss (commonly associated with mutable structs). This should be a class:
[DataContract]
public class StatusInfo
{
[DataMember] public int Total {get;set;}
[DataMember] public string Authority {get;set;}
}
It will now behave as you think it should. If you want it to be an immutable struct, that would be OK (but data-binding would be one-way only, of course):
[DataContract]
public struct StatusInfo
{
[DataMember] public int Total {get;private set;}
[DataMember] public string Authority {get;private set;}
public StatusInfo(int total, string authority) : this() {
Total = total;
Authority = authority;
}
}
However, I would first question why this is a struct in the first place. It is very rare to write a struct in .NET languages. Keep in mind that the WCF "mex" proxy layer will create it as a class at the consumer anyway (unless you use assembly sharing).
In answer to the "why use structs" reply ("unknown (google)"):
If that is a reply to my question, it is wrong in many ways. First, value types as variables are commonly allocated (first) on the stack. If they are pushed onto the heap (for example in an array/list) there isn't much difference in overhead from a class - a small bit of object header plus a reference. Structs should always be small. Something with multiple fields will be over-sized, and will either murder your stack or just cause slowness due to the blitting. Additionally, structs should be immutable - unlesss you really know what you are doing.
Pretty much anything that represents an object should be immuatable.
If you are hitting a database, the speed of struct vs class is a non-issue compared to going out-of-process and probably over the network. Even if it is a bit slower, that means nothing compared to the point of getting it right - i.e. treating objects as objects.
As some metrics over 1M objects:
struct/field: 50ms
class/property: 229ms
based on the following (the speed difference is in object allocation, not field vs property). So about 5x slower, but still very, very quick. Since this is not going to be your bottleneck, don't prematurely optimise this!
using System;
using System.Collections.Generic;
using System.Diagnostics;
struct MyStruct
{
public int Id;
public string Name;
public DateTime DateOfBirth;
public string Comment;
}
class MyClass
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public string Comment { get; set; }
}
static class Program
{
static void Main()
{
DateTime dob = DateTime.Today;
const int SIZE = 1000000;
Stopwatch watch = Stopwatch.StartNew();
List<MyStruct> s = new List<MyStruct>(SIZE);
for (int i = 0; i < SIZE; i++)
{
s.Add(new MyStruct { Comment = "abc", DateOfBirth = dob,
Id = 123, Name = "def" });
}
watch.Stop();
Console.WriteLine("struct/field: "
+ watch.ElapsedMilliseconds + "ms");
watch = Stopwatch.StartNew();
List<MyClass> c = new List<MyClass>(SIZE);
for (int i = 0; i < SIZE; i++)
{
c.Add(new MyClass { Comment = "abc", DateOfBirth = dob,
Id = 123, Name = "def" });
}
watch.Stop();
Console.WriteLine("class/property: "
+ watch.ElapsedMilliseconds + "ms");
Console.ReadLine();
}
}
I can only guess why they only support properties: perhaps because it seems to be a universal convention in the .NET framework never to expose mutable fields (probably to safeguard binary compatibility), and they somehow expected all programmers to follow the same convention.
Also, although fields and properties are accessed with the same syntax, data binding uses reflection, and (so I've heard) reflection must be used differently to access fields than to access properties.

How do I call this list from another class in C#?

I am still new to the whole C# thing but I found this code posted from grovesNL about 5 years ago which I believe will work.
namespace DataAccessClass
{
public class FileReader
{
static void Main(string[] args)
{
List<DailyValues> values = File.ReadAllLines("C:\\Users\\Josh\\Sample.csv")
.Skip(1)
.Select(v => DailyValues.FromCsv(v))
.ToList();
}
}
public class DailyValues
{
DateTime Date;
decimal Open;
decimal High;
decimal Low;
decimal Close;
decimal Volume;
decimal AdjClose;
public static DailyValues FromCsv(string csvLine)
{
string[] values = csvLine.Split(',');
DailyValues dailyValues = new DailyValues();
dailyValues.Date = Convert.ToDateTime(values[0]);
dailyValues.Open = Convert.ToDecimal(values[1]);
dailyValues.High = Convert.ToDecimal(values[2]);
dailyValues.Low = Convert.ToDecimal(values[3]);
dailyValues.Close = Convert.ToDecimal(values[4]);
dailyValues.Volume = Convert.ToDecimal(values[5]);
dailyValues.AdjClose = Convert.ToDecimal(values[6]);
return dailyValues;
}
}
}
I am trying to read a csv file skipping the header and get it into a list that is accessible from another class. So my Architecture is DataAccessClass that has a class called FileReader and a class called Values. My task is to read this csv file into class FileReader and then to create an object list to hold it in the class Values. When I go to the Values class to call it I can't figure it out. This is how I am trying to call it. It is saying DailyValues.FromCsv(string) is a method that is not valid.
public List<string> GetList()
{
return DataAccessClass.DailyValues.FromCsv.dailyValues;
}
I want to be able to access this list further up the stack.
Your expression DataAccessClass.DailyValues.FromCsv.dailyValues is the culprit.
DataAccessClass.DailyValues.FromCsv is valid, and references the static method named FromCsv in the class DataAccessClass.DailyValues. But then going on by adding .dailyValues is incorrect. It is a method, nothing to peek into and extract stuff using ..
You could (if that was the intention) call the function, and directly work with the result:
DataAccessClass.DailyValues.FromCsv(some_csv_string) is an expression of type DailyValues. There you could then access - as an example - 'High' with:
DailyValues dv;
dv = DataAccessClass.DailyValues.FromCsv(some_csv_string);
dosomething(dv.High);
But for that to work, High would have to have the visibility of public.

Calculate difference in property

I have converted a list of JSON objects to a generic list.
The Data structure on the items is as following
public class Person
{
private string Name;
private int Age;
private string Weightloss;
}
The Weightloss string is of type "109-102" and I need to calculate how much each person has lost in weight since they signed up. I my examlpe it'd be 7. How to I, using LINQ Method syntax, calculate each weight loss (or gain). I assume I'll need to split up the string but I'm not really sure how
Rather odd question, but if Linq is what you want, here is how one can go about it:
Create a function inside your class to calculate the weight difference:
public class Person
{
//Constructor
public Person(string name, int age, string weightLoss)
{
Name = name;
Age = age;
Weightloss = weightLoss;
}
public string Name;
private int Age;
private string Weightloss;
/// <summary>
/// Calculates the weight difference from the WeightLoss property.
/// </summary>
/// <returns></returns>
public int GetWeightLoss()
{
//Get the values
var parts = Weightloss.Split('-')
.Select(value => Convert.ToInt32(value))
.ToArray();
//Calculate the difference
var difference = parts[0] - parts[1];
return difference;
}
}
Not clean and I personally dislike it but it's homework so...
I added a constructor for initialization and changed the Name field to public so you can output it:
var list = new List<Person>()
{
new Person("Juan", 30, "109-102"),
new Person("Max", 35, "119-103"),
new Person("John", 40, "109-105"),
};
//Figure out the largest loss
var maxLossPerson = list.OrderByDescending(p => p.GetWeightLoss()).First();
Console.WriteLine($"{maxLossPerson.Name} lost the most with {maxLossPerson.GetWeightLoss()} pound(s)");
Output:
Max lost the most with 16 pound(s)
You're either going to use a string split or a regular expression.
Assuming your string is always formatted "Weight1-Weight2", a string split would be fairly simple:
public int[] ParseWeights(string weightString) {
var weights = weightString.Split('-');
var beginningWeight = Convert.ToInt32(weights[0]);
var endingWeight = Convert.ToInt32(weights[1]);
return new int[] {beginningWeight, endingWeight};
}
Add another property to Person:
public class Person
{
private string Name;
private int Age;
private string Weightloss;
public int WeightLost
{
get
{
int[] values = Weightloss.Split('-').Select(i => int.Parse(i)).ToArray();
return values[0] - values[1];
}
}
}
If you look for a even more Linq way, you can use the follow way:
private string Weightloss;
public int WeightLossInt => Weightloss
.Split('-')
.Select((value, index) => index == 0 ? int.Parse(value) : -int.Parse(value))
.Sum();
}

AutoFixture : pass an argument to specimen builder

(I didn't find a way to do this, from source code it appears it is not supported, but I might have overlooked it)
I would like to do something akin to:
(new Fixture())
.CreateAnonymous<Circle>(
new CircleSpecification { MinRadius = 1, MaxRadius = 5 }
);
So this is a variation on a similar seed-idiom present in AutoFixture already, but seed idiom is very hard coded (or so I think).
Quiestion: Is it possible to customize a fixture to accept an argument for a specimen?
The best idea I have so far is to build a special Specification class that includes the result object, so that you can do:
public class CircleSpecification {
public double MinRadius { get; set; }
public double MaxRadius { get; set; }
public Circle Circle { get; set; }
}
so that I can register CircleSpecificationSpecimenBuilder that can be used:
Circle circle = Fixture.CreateAnonymous<CircleSpecification>(
new CircleSpecification { MinRadius = 0.0, MaxRadius = 5.0 }).Circle;
notice that to use CreateAnonymous with seed overload seed argument type has to match method return type.
If you want to assign a value while creating an anonymous instance of Circle you can use the Build method:
var fixture = new Fixture();
var c = fixture
.Build<Circle>()
.With(x => x.Radius, 3)
.CreateAnonymous();
However, if there's nothing special about the Radius property, why not simply assign it a value afterwards?
var fixture = new Fixture();
var c = fixture.CreateAnonymous<Circle>();
c.Radius = 3;
The latter option is much more declarative, and will enable you to use AutoFixture's xUnit.net integration to write a much terser test that removes all the accidental complexity:
[Theory, AutoData]
public void Test3(Circle c)
{
c.Radius = 3;
// Act and assert here
}

Distributing RDLC output as an email attachment

Our winforms application has long allowed a "print" option which basically uses RDLC.
The customer has requested that we add a feature allowing users to send the "printed" output via email.
Now, we know that an EMF file is created (in the TEMP folder) as a sort of hidden byproduct of our current printing process.
Seems to us we can simply grab this EMF file and attach it to a new email and the job is done.
Is this the best option?
Can we rely on an EMF file be opened by any Windows machine?
How we identify the EMF file? ... just seems to be named %TEMP%\DiaryGrid_1.emf currently. OK so DiaryGrid is the name of our RDLC file but the _1 gets added somewhere along the way.
I did it before. I did it exporting programatically the report to a pdf to a specific location, then we email the pdf file and delete it. I will try to find the code for you (Not in home now)
EDITED:
Sorry for the later. Now i'm in home and I will give you some code blocks that I think will give you some help to acomplish your task. I will include some comments to the code so you can understand some things that are specific in my project. This code are tested and are working well in my clients, but i'm sure that it can be improved. Please, let me know if you can improve this code ;)
First of all, we will export the report to pdf.
private string ExportReportToPDF(string reportName)
{
Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string filenameExtension;
byte[] bytes = ReportViewer1.LocalReport.Render(
"PDF", null, out mimeType, out encoding, out filenameExtension,
out streamids, out warnings);
string filename = Path.Combine(Path.GetTempPath(), reportName);
using (var fs = new FileStream(filename, FileMode.Create))
{
fs.Write(bytes, 0, bytes.Length);
fs.Close();
}
return filename;
}
Now, we need a class that control the Mail system. Every mail system has their own caracteristics, so maybe you will need modify this class. The behaviour of the class is simple. You only need to fill the properties, and call the Send method. In my case, windows don't let me delete the pdf file once I send it (Windows says the file is in use), so I program the file to be deleted in the next reboot. Take a look to the delete method. Please, note that the send method use a cutom class named MailConfig. This is a small class that has some config strings like Host, User Name, and Password. The mail will be send using this params.
public class Mail
{
public string Title { get; set; }
public string Text { get; set; }
public string From { get; set; }
public bool RequireAutentication { get; set; }
public bool DeleteFilesAfterSend { get; set; }
public List<string> To { get; set; }
public List<string> Cc { get; set; }
public List<string> Bcc { get; set; }
public List<string> AttachmentFiles { get; set; }
#region appi declarations
internal enum MoveFileFlags
{
MOVEFILE_REPLACE_EXISTING = 1,
MOVEFILE_COPY_ALLOWED = 2,
MOVEFILE_DELAY_UNTIL_REBOOT = 4,
MOVEFILE_WRITE_THROUGH = 8
}
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool MoveFileEx(string lpExistingFileName,
string lpNewFileName,
MoveFileFlags dwFlags);
#endregion
public Mail()
{
To = new List<string>();
Cc = new List<string>();
Bcc = new List<string>();
AttachmentFiles = new List<string>();
From = MailConfig.Username;
}
public void Send()
{
var client = new SmtpClient
{
Host = MailConfig.Host,
EnableSsl = false,
};
if (RequireAutentication)
{
var credentials = new NetworkCredential(MailConfig.Username,
MailConfig.Password);
client.Credentials = credentials;
}
var message = new MailMessage
{
Sender = new MailAddress(From, From),
From = new MailAddress(From, From)
};
AddDestinataryToList(To, message.To);
AddDestinataryToList(Cc, message.CC);
AddDestinataryToList(Bcc, message.Bcc);
message.Subject = Title;
message.Body = Text;
message.IsBodyHtml = false;
message.Priority = MailPriority.High;
var attachments = AttachmentFiles.Select(file => new Attachment(file));
foreach (var attachment in attachments)
message.Attachments.Add(attachment);
client.Send(message);
if (DeleteFilesAfterSend)
AttachmentFiles.ForEach(DeleteFile);
}
private void AddDestinataryToList(IEnumerable<string> from,
ICollection<MailAddress> mailAddressCollection)
{
foreach (var destinatary in from)
mailAddressCollection.Add(new MailAddress(destinatary, destinatary));
}
private void DeleteFile(string filepath)
{
// this should delete the file in the next reboot, not now.
MoveFileEx(filepath, null, MoveFileFlags.MOVEFILE_DELAY_UNTIL_REBOOT);
}
}
Now, you can create a form to ask for the destinataries, add some validation, etc, return to you an instance of the Mail class... or you can simply "hard code" the values and fill the class.
Here is the code that I use in a button to call this form, in my example it is named SendMailView.
private void BtnSendByMail_Click(object sender, EventArgs e)
{
SendMailView sendMailView = new SendMailView();
if (sendMailView.ShowDialog()== DialogResult.OK)
{
Mail mail = sendMailView.CurrentItem;
mail.AttachmentFiles.Add(ExportReportToPDF("Invoice.pdf"));
mail.DeleteFilesAfterSend = true;
mail.RequireAutentication = true;
mail.Send();
}
sendMailView.Dispose();
}
In this example senMailView.CurrentItem is the instance of the mail class. We simply need to call to the Send methis and the work is done.
This is the largest answer I ever wrote in SO... I hope it help you :D If you have any problem using it, call me. By the way, i'm not very proud of my english, so forgive me if the text has any mistake.

Resources