Saving a list between applications in the .NET property settings - c#

I have a simple list, like this:
fruitList = new FruitList();
Apple fruit1 = new Apple("red", "small");
Banana fruit2 = new Banana("yellow", "big");
fruitList.AddFruit(fruit1);
fruitList.AddFruit(fruit2);
My program displays this in a Textbox:
textbox.Text = fruitList.DescribeCurrentFruit()
+
public string DescribeCurrentFruit()
{
string description;
if (fruitStock.Count > 0)
{
description = fruitStock[fruitCurrentlyDisplayed].Description();
}
else
{
description = "No Fruits in stock";
}
return description;
}
Currently, the List's two current objects/items (fruit1, fruit2) are automatically loaded as they are a part of my Window Form's load_event. However, if they're not a part of the load_event, or if I want to add more items/objects to the list at runtime, then permanently save them, how can I do so?
Well, I can do so by saving items in the project's property settings. (Serialization is an alternative option, but far too complex for me, and I want the simplest solution.) How do I go about this? Is there any sample code? I understand I first need to add items into my properties, but struggle even at this step.

Related

How to avoid the overwriting in the DataBinding?

im new at programming and need help here... I want to create a Binding with a Combobox Item.
But the DataBinding is not adding a new DataBind, it overwrites the old one because of the loop. So i want if you select a "Profilname" in the Combobox that the "Path" will be displayed.
But so far, just the last loaded .txt file will be displayed because of the overwrite.
Here is now my question: How to avoid the overwrite of the DataBind in the (foreach)-loop?
For information: There is a folder which contains many .txt-files, which are all called: "profile.txt". The Programm search for all the files with a loop and then search in the files with another loop a line, which contains the word "profile_name". And then the Name has to be displayed in the ComboBox and the Path has to be binded to the "Item"/"Text" in the ComboBox.
I hope this is understandable and sorry if my code is confusing or not very strong written, im learning...
foreach (string profiletxt in Directory.EnumerateFiles(profiledirectory, "profile.txt", SearchOption.AllDirectories))
{
foreach (string line in System.IO.File.ReadAllLines(profiletxt))
{
if (line.Contains("profile_name"))
{
string remLine = line.Remove(0, 15);
string dLine = remLine.Replace("\"", "");
// dataBinding
var listProfiles = new List<Profile>() {
new Profile() {Path = profiletxt, Name = dLine,},
};
materialComboBox1.DataSource = listProfiles;
materialComboBox1.DisplayMember = "Name";
materialComboBox1.ValueMember = "Path";
}
}
if (materialComboBox1.SelectedIndex == -1)
{
MessageBox.Show("Error, couldn't find Profiles");
}
}
public class Profile
{
public string Path { get; set; }
public string Name { get; set; }
}
a ComboBox uses its ItemSource containing the available items. In your inner foreach loop you declare a new profile list for every find of profile item:
var listProfiles = new List<Profile>() {
new Profile() {Path = profiletxt, Name = dLine,},
};
materialComboBox1.DataSource = listProfiles;
Instead, you'd probably like to create a new Profile list before the first foreach loop
var listProfiles = new List<Profile>();
and in the inner loop, add your new finding to the list
listProfiles.Add(new Profile() {Path = profiletxt, Name = dLine});
Then, after the outer loop, you may assign the new ItemSource only once.
There are other newby design flaws in your code:
there should be no need to set DisplayMember and ValueMember in the .xaml.cs "code behind". Rather it belongs into the xaml code itself as these are static.
As a more general advise, consider not doing any kind of "business rules stuff" or data holding in your code behind. Rather you like to separate your UI ("View") from your data ("Model") while a "ViewModel" separates these two and implements the business rules. There are tons of good introductions on this MVVM programming pattern out there.

Managing Multiple settings in c#

I have created two settings file under properties in c#. Basically I have to apply settings based on a particular set of condition
for example the settings file are "myset1" and "myset2"
both these settings have similar structure
myset1
price = 100
qty = 100
myset2
price = 150
qty = 20
in my application, if value of variable "appColor" is "blue" myset1 has to be used if variable "appColor" is "red" myset2 has to be used.
in my code
productPrice.Text = //based on the "appColor" selection value from myset1 or myset2 has to be displayed.
I tried this but not working
Settings setSelector = new Settings();
if(appColor == "blue")
{
setSelector = myset1.Default;
}
else(appColor == "red")
{
setSelector = myset2.Default;
}
I am getting error that "cannot convert source type "myset1" to settings"
EDIT: my aim is that productPrice.Text = setSelector.Price; remains same even when settings are changed so I don't have to change code here and just have to change the settings. basically full forms gets filled based on the settings selected.
any help would be appreciated
I tried below code. it worked correctly.
I have two Textboxes, in which i am setting Price and Qty based on color.
Object obj = new Object();
if(appColor == "blue")
{
obj = (System.Configuration.SettingsPropertyCollection)Properties.Settings.Default.Properties;
}
else(appColor == "red")
{
obj = (System.Configuration.SettingsPropertyCollection)Properties.Settings1.Default.Properties;
}
foreach (System.Configuration.SettingsProperty p in Properties.Settings.Default.Properties)
{
if (p.Name=="Qty")
textBox1.Text = p.DefaultValue.ToString();
else if (p.Name=="Price")
textBox2.Text = p.DefaultValue.ToString();
}
I Hope this helps :)
After playing around with it a bit and referencing this MSDN article specifically the last section on adding alternate sets of settings.
To Add an Additional Set of Settings
From the Project menu, choose Add New Item. The Add New Item dialog box opens.
In the Add New Item dialog box, select Settings File.
In the Name box, give the settings file a name, such as SpecialSettings.settings, and click Add to add the file to your
solution.
In Solution Explorer, drag the new settings file into the Properties folder. This allows your new settings to be available in
code.
Add and use settings in this file as you would any other settings file. You can access this group of settings through the
Properties.SpecialSettings object.
I then realized that each settings file is its own separate class therefore you have to go back to a common class. By doing so you will loose your individual properties and have to cast it to the proper class. I then looked at this SO question searching for dynamic casting. According to JaredPar's answer it appears that the easiest way to do this would be to use the dynamic keyword and let the class type be figured out at runtime.
i.e.
Class level Declaration:
dynamic setSelector;
Intializing it during Form Load:
private void Form1_Load(object sender, EventArgs e)
{
if(appColor == "blue")
{
setSelector = Properties.myset1.Default;
}
else if(appColor == "red")
{
setSelector = Properties.myset2.Default;
}
textBox1.Text = setSelector.qty.ToString();
}

Create/Increment ObservableCollection On Button Click

I am looking to see if it is possible to be able to increment an ObservableCollectionevery time a button is clicked?
ObservableCollection<string> _title = new ObservableCollection<string>();
public ObservableCollection<string> Title
{
get { return _title; }
set
{
_title = value;
OnPropertyChanged(() => Title);
}
}
As shown from the C# code above, I have an ObservableCollection for a Title. Currently, when I add a new title, every title goes into the same collection. However, what I am aiming to achieve is; every time the "Add Title" button is pressed, a new title is added and a new ObservableCollection is created. Is this possible, and how can it be done?
EDIT1
At the moment I dynamically create Textboxes and then add whatever string I want to that Textbox. From there I save the Stackpanel, named 'Content', into a .txt file. In this file it will hold the Textboxs that have been created. (It does not save the string into that file due to the textbox being binded). I then thought the strings would be saved into a list, and when I load the Stackpanel back up from the .txt file the string would get added back to the Textbox.
EDIT2
I have changed a bit of code:
public ViewModel()
{
this.AddTitleCommand = new RelayCommand(new Action<object>((o) => OnAddTitle()));
}
private void OnAddTitle()
{
NewTitle += titleName;
}
When doing this it is not adding my string as a word it is separating the letters in my string in separate titles.
If I understand you correctly, each time your Button is pressed, you want to add a new string into a new collection. You then said that you will add other values into each collection... this sounds like you're trying to fulfil your requirements in the wrong way, but you didn't tell us what those were, so we can't help you with that. Here's how you can add a new collection each time:
private string newTitle = string.Empty;
private ObservableCollection<ObservableCollection<string>> collections = new
ObservableCollection<ObservableCollection<string>>();
public ObservableCollection<ObservableCollection<string>> Collections
{
get { return collections; }
set { collections = value; OnPropertyChanged(() => Collections); }
}
public string NewTitle
{
get { return newTitle; }
set { newTitle = value; OnPropertyChanged(() => NewTitle); }
}
public void AddCollection()
{
ObservableCollection<string> collection = new ObservableCollection<string>();
collection.Add(NewTitle);
Collections.Add(collection);
}
The NewTitle property could be data bound to a TextBox in the UI allowing users to enter the new values and when the Button is pressed, the AddCollection method would add it into a new collection and then add that into the Collections collection.
I still think that this is not a good idea though.
UPDATE >>>
Please stop what you're doing... programs are not written like that. We save data, the strings, not UI elements. There is absolutely no point in saving the UI elements along with all their extra property values that you have no interest in. Whatever method you have of displaying the strings in the TextBoxes can be reused each time the data is loaded.
ObservableCollection provides a constructor that takes an IEnumerable so use it to create a new instance with the same titles and add your new title afterward :
ObservableCollection<string> newCollection = new ObservableCollection<string>(Title);
newCollection.Add(theNewTitle)
Title = newCollection;

Listview Add Items not appearing C#

I'm working on a small program as part of my A Level Computing course that is designed to track orders. It is written in C# using the Windows Forms.
I am having an issue where I enter all the information for a new order and then press OK and it should update the ListView with the information. I have my ListView in Detail view with 4 columns but nothing ever gets added to the ListView. The section of code that should add the items to the ListView is being executed and is not throwing any errors or causing the program to crash but nothing is being added. Its weird because I am using the exact same method that I used in my little prototype mock up but for some reason now it is not working.
All the things I've found on here or on the internet seem to suggest its an issue with the View mode of the ListView and I've tried modifying this property to no avail.
Any ideas why this section of code is refusing to add anything to the ListView?
//Create an array to store the data to be added to the listbox
string[] orderDetails = { Convert.ToString(id + 1), rNameBox.Text, dateBox.Value.ToString(), orderBox.Text };
//DEBUGGING
Console.WriteLine(orderDetails[0]);
Console.WriteLine(orderDetails[1]);
Console.WriteLine(orderDetails[2]);
Console.WriteLine(orderDetails[3]);
//END DEBUGGING
//Add the order info to the ListView item on the main form
var listViewItem = new ListViewItem(orderDetails);
ths.listView1.Items.Add(listViewItem);
If you need any more information just say. Apologies if this is in the wrong format or something this is my first time here.
Your problem is that your ListViewItem contains a string array and it has no useful way of displaying it.
What you should be doing (there are a number of ways of doing this, but here's one) is creating a class, OrderDetail, with an Id, a Name, a Date, and so on. Give it a ToString() method (public override string ToString()) which returns what you want to display, e.g.:
public override string ToString()
{
return this.Name;
}
Create an instance of OrderDetail and set its properties. Create ListViewItem giving it the OrderDetail instance and add to the ListView. Repeat for as many OrderDetail instances you want.
Cheers -
Added: code which works:
int id = 12;
string rNameBoxText = "rName";
DateTime dateBoxValue = DateTime.Now;
string orderBoxText = "order";
string[] orderDetails = { Convert.ToString(id + 1), rNameBoxText, dateBoxValue.ToString(), orderBoxText };
//DEBUGGING
Console.WriteLine(orderDetails[0]);
Console.WriteLine(orderDetails[1]);
Console.WriteLine(orderDetails[2]);
Console.WriteLine(orderDetails[3]);
//END DEBUGGING
this.listView1.Columns.Clear();
this.listView1.Columns.Add("Id");
this.listView1.Columns.Add("rName");
this.listView1.Columns.Add("Date");
this.listView1.Columns.Add("Order");
this.listView1.View = View.Details;
//Add the order info to the ListView item on the main form
var listViewItem = new ListViewItem(orderDetails);
this.listView1.Items.Add(listViewItem);

Click a custom control and show some variables related to it in another control

in my Win Forms app I create an array of dynamic custom controls inside a loop. These, lets call them 'boxes', are like my basic pieces of information. I also create string arrays in other parts of the code that contain the information of this 'boxes', so that for example string[3] is a variable of box[3] and so does stringa[3], stringb[3], stringc[3]... all the arrays with the same index are related to the box with that index. Hope I make myself clear.
Only 2 of this strings are shown in 2 labels inside each custom control 'box' in the array, but the others are there because I want to make something so that when the user clicks one of these controls the other strings can be shown in another control. Sort of something like "More Information...". All the 'boxes' in the array need to have the same event handler because I create +100.
To put it more into context, each custom control 'box' in the array shows the Symbol and the Price of a stock and I want that when the user clicks on each stock more quote information is shown on another special control which is like a placeholder for "More info".
I am thinking of 2 ways to do it:
If I could "detect" the index of the clicked control (which is the same in the strings related to it), I could just set this to an int j and all I have to do is show all the strings a,b,c... with index j. Unfortunately I cannot find a way to do this, maybe it is not even possible.
The other way I have thought is to create some properties for my custom control which "store" this variables, and in my app instead of assigning strings I would set properties for each control, which I could later retrieve when the control is clicked. I haven't tryed this because I don't know exactly how to do it.
What do you think? Do you know how can I achieve this or do you have a different idea that will work? Please help! Thanks in advance.
It's kind of a broad implementation question since there are countless ways you could implement something like this.
If you are creating two collections, one with the buttons and one with the information, you potentially could just assign each of the buttons 'Tag' properties to point to the corresponding info and assign a generic OnClick event handler that displays the info.. something like:
infoControl.text = ((InfoClass)((Button)Sender.Tag)).pieceOfInformation;
But again there are many ways to do this, and the choice comes down to how you store your information.
For your first method, you could have a property of your custom control that is the index.
public class Box : Control
{
// ...existing code
private int index;
public int Index
{
get
{
return index;
}
set
{
index = value;
}
}
}
OR
For your second method, you could have a property of your custom control that is the additional info string.
public class Box : Control
{
// ...existing code
private string extraInfo;
public string ExtraInfo
{
get
{
return extraInfo;
}
set
{
extraInfo = value;
}
}
}
In either case, you could then access the proper information right in your click handler for the "box".
i don't know about the first way - got to noodle around more, but in the second way you can extended your custom or built-in control: for example:
public class ExtendedLabel: Label
{
public string[] MoreInfo { get; set; }
}
and initialize it
public TestForm()
{
InitializeComponent();
ExtendedLabel label = new ExtendedLabel();
label.MoreInfo = new string[] { "test" };
this.Controls.Add(label);
label.AutoSize = true;
label.Location = new System.Drawing.Point(120, 87);
label.Name = "label1";
label.Size = new System.Drawing.Size(35, 13);
label.TabIndex = 0;
label.Text = label.MoreInfo[0];
}
And later in your event handler you can use the inside information

Categories