I am trying to add an image to a list of images when a checkbox is checked, and when the checkbox is unchecked I want to remove the image from the list. Adding the image works fine, but when the box is unchecked its not removing the image from the list.
List<Image> images = new List<Image>();
private void chkRadiation_CheckedChanged(object sender, EventArgs e)
{
if (chkRadiation.Checked == true && images.Count < 4)
{
images.Add(Image.FromFile(#"C:\Users\joe\documents\radiation.gif"));
}
else if (chkRadiation.Checked == false)
{
images = images.Where(x => x != Image.FromFile(#"C:\Users\joe\documents\radiation.gif")).ToList();
}
else if
(chkRadiation.Checked == true)
{
MessageBox.Show("Please select only 3 images");
chkRadiation.Checked = false;
}
}
I also tried
images.Remove(Image.FromFile(#"C:\Users\joe\documents\radiation.gif"));
It did not work either.
What am I doing wrong?
The problem is that you're working with instances of a class Image, so all your comparisons, and images.Remove are working off references.
When you do Image.FromFile(#"C:\Users\joe\documents\radiation.gif") you're creating a new image object/reference, that happens to contains the same data as one in the list, but because the reference isn't the same, removing it won't work.
You might be better to recode using a Generic.Dictionary<String,Image> where the key string is the path of the image (in the absence of any better key). That way you can check if there are items in the dictionary with the path and remove them the same way.
By default List.Remove uses instance value comparision to detect which element to remove. Since you're loading the image again to remove it, that's a different instance. I would keep track of the index in which an image is added and use that to remove it from the list. CheckBox.Tag might be a good place to hide the index...
with the expression
x != Image.FromFile(#"C:\Users\joe\documents\radiation.gif")
you compare two objects:
Object one: x is the image already in your collection.
Object two: is
the image which gets create at this moment based on the source path.
as you compare the two it will always return false as these are two different instances of the object Image.
How the operator == works
Related
What I want to do, is to search in a ComboBox, for a word, or a part of a word like this:
For example I have these entries in my combobox:
abc
Abc
Dabc
adbdcd
And when I search for "abc", it should show me every one in the list, except "
adbdcd"
I fill my combobox from a mysql database, so my items are in a "Collection".
I have autocomplete enabled (mode: SuggestAppend, source: ListItems)
This is the code, I am using right now:
private void comboBox1_KeyPress(object sender, KeyPressEventArgs e)
{
comboKeyPressed();
}
private void comboBox1_TextChanged(object sender, EventArgs e)
{
if (comboBox1.Text.Length == 0) comboKeyPressed();
}
private void comboKeyPressed()
{
comboBox1.DroppedDown = true;
object[] originalList = (object[])comboBox1.Tag;
if (originalList == null)
{
// backup original list
originalList = new object[comboBox1.Items.Count];
comboBox1.Items.CopyTo(originalList, 0);
comboBox1.Tag = originalList;
}
// prepare list of matching items
string s = comboBox1.Text.ToLower();
IEnumerable<object> newList = originalList;
if (s.Length > 0)
{
newList = originalList.Where(item => item.ToString().ToLower().Contains(s));
}
// clear list (loop through it, otherwise the cursor would move to the beginning of the textbox...)
while (comboBox1.Items.Count > 0)
{
comboBox1.Items.RemoveAt(0);
}
// re-set list
comboBox1.Items.AddRange(newList.ToArray());
}
The problem with this code, is if I search for "abc" in my example list, "adbdcd" will show up too. And this code randomly crashes my program when I hit backspace in the combobox.
This is the root cause of crash:
while (comboBox1.Items.Count > 0)
{
// this is raising exception if you try to remove the last item
// Check the doc of RemoveAt
comboBox1.Items.RemoveAt(0);
}
use that instead:
comboBox1.Items.Clear();
However what you are trying to achieve is still unclear.
If Text of combox is empty, then nothing will ever happen apart from clearing and re adding the same items to the combo box.
My understanding is that you're trying to duplicate the completion behavior while having it enabled. It can raise exception too (AccessViolationException) since you try to modify the Items collection while the framework tries to do the same.
If you're not happy with the default auto completion behavior, disable it and try to implement it completely inside the comboKeyPressed method.
It means then calling it whenever text is modified.
Modification of your code to make it work (Disable auto completion though):
private void comboBox1_TextChanged(object sender, EventArgs e)
{
comboKeyPressed();
}
private void comboKeyPressed()
{
if (comboBox1.Text == lastFilter)
{
return;
}
object[] originalList = (object[]) comboBox1.Tag;
if (originalList == null)
{
// backup original list
originalList = new object[comboBox1.Items.Count];
comboBox1.Items.CopyTo(originalList, 0);
comboBox1.Tag = originalList;
}
// prepare list of matching items
string s = comboBox1.Text.ToLower();
IEnumerable<object> newList = originalList;
if (s.Length > 0)
{
newList = originalList.Where(item => item.ToString().ToLower().Contains(s));
}
// clear list (loop through it, otherwise the cursor would move to the beginning of the textbox...)
comboBox1.Items.Clear();
// re-set list
comboBox1.Items.AddRange(newList.ToArray());
comboBox1.Select(Text.Length -1, 0);
lastFilter = comboBox1.Text;
comboBox1.DroppedDown = true;
}
So, you want fulltext search.
Where is your data coming from? What kind of data is it? What are the edge cases?
For databases, I like to use Sphinx for fulltext indexing.
For in-memory data, efficient fulltext search algorithms include Suffix Arrays, Suffix Trees, and Patricia Tries. Implementing them can be a fun (and time-consuming) challenge. Or you might find a suitable implementation online. You can find barebones implementations of these algorithms, as well as more polished implementations of fulltext search, such as Lucene.
To give you a sketch of how they work, imagine taking every possible suffix of every word that you store, e.g. needle:
needle
eedle
edle
dle
le
e
Put all these suffixes into an ordered data structure, such as a sorted array or list (for static data) or a B-tree or SortedDictionary (if data is added regularly). After inserting needle, it would contain:
dle
e
edle
eedle
le
needle
Now we can search for any part of a word (e.g. edl) using binary search or better, and see if we have a hit.
To extract more information than just whether or not we have a hit, we could add data to, for example, the values of the SortedDictionary. (We used the suffixes as keys.) Interesting data could be the entire word, or perhaps the original text and location where the word was encountered.
If the number of entries to search from is always low - perhaps no more than a few hundred - then a simple implementation will suffice.
// Select all words that contain our query string
var matchingWords = wordList.Where(word => word.Contains(query));
This is the naive, linear implementation that will become very slow for large data. For small data, though, it is super easy. Just feed the new subset to your combo box.
You might want to add case-insensitivity to the Contains() call, using its optional second parameter.
Work on Vs2010 EF,C#.
Have two list(oLisTranItem,oListTaxItem) ,need to copy one list properties values in another list ,then I need to work on new list.Problem is after copy content element one list to another list any type of changes impact on both list ,why this happen ,I just change on list but changes occur in both list
Please check my bellow syntax.
List<TransactionItem> oLisTranItem = new List<TransactionItem>();
List<TransactionItem> oListTaxItem = new List<TransactionItem>();
oLisTranItem = _TransactionItem;
oListTaxItem = _TransactionItemTax;
TransactionItem tmpItem = new TransactionItem();
tmpItem = oLisTranItem.Where(item => item.QuotationDetailID == quotationDetailID && item.Action != Entity.ActionMode.Delete && item.IsDeleted == false).FirstOrDefault();
if (tmpItem.IsNotNull())
{
tmpItem.Action = Entity.ActionMode.Add;
oListTaxItem.Add(tmpItem);
}
else
{
_TransactionItemTax = new List<TransactionItem>();
}
int nCounter = 5;
foreach (TransactionItem item in oListTaxItem)
{
if (item.QuotationTaxID ==0)
{
nCounter = nCounter + 1;
item.QuotationTaxID = nCounter;
}
}
Please help me to identify why this problem aries,how to solve this problem.
If have any query please ask,Thanks in advanced.
TransactionItem is probably a class, right? And not a struct.
Every type that's a class is, by default, a reference type. That means what you have in the lists are not the real values of the transaction items, but references (think C++ pointers) to those values. So when you copy data from one list to the other, you're just copying references.
You need to clone the items from one list to another. Give your class a method to clone instances, and use that method to copy items from one list to another.
I'm working on an application of which requires me to have one list-box to hold data.
I'm having a little issue when deleting an object from a list-box. The issue comes into play when I fill the list-box with items from TWO separate lists.
Normally to delete the object I would get it's index and then remove it from the list in a separate class then reload the list-box to reflect the changes but in certain instances I need to fill the list-box with objects from two different lists and determining the origin of the object to delete from one of the two lists, well I'm not entirely sure how to do this.
this code is populating the list-box control.
//clear all items in the listbox
ViewListBox.Items.Clear();
//create the lists
List listOfPickups = visits.listPickups();
List listOfdeliveries = visits.listDeliveries();
//populate
ViewListBox.Items.AddRange(listOfPickups.ToArray());
ViewListBox.Items.AddRange(listOfdeliveries.ToArray());
this is how i delete when i am only loading the listbox from one list.
if (ViewListBox.SelectedIndex < 0)
{
EditSelectBtn.Enabled = false;
DeleteSelectBtn.Enabled = false;
}
else
{
if (MessageBox.Show("are you sure you want to delete the selected item?", "Are You Sure?", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
visits.removePickup(this.ViewListBox.SelectedIndex);
//refresh listbox.
updateList("pickups");
}
else
{
//clicked no so do nothing!
ViewListBox.ClearSelected();
}
}
Any help would be greatly appretiated.
You can define type of selected item, and remove it from list with simple condition. Also removing by index will not help you here. Pass whole object instead
object item = ViewListBox.SelectedItem;
if (item is Pickup)
visits.removePickup(item);
else
visits.removeDelivery(item);
If items have same type, then use some other way to get item type (e.g. value of some property).
UPDATE One catch - you can determine item origin by comparing SelectedIndex with listOfPickups length, because you are adding pickup items first. If index is greater, than pickups count, then you are removing delivery. Subtract pickups count from selected index to get index of delivery item you need to remove.
List<Pickup> listOfPickups = visits.listPickups();
List<Delivery> listOfdeliveries = visits.listDeliveries();
ViewListBox.Items.AddRange(listOfPickups.ToArray());
ViewListBox.Items.AddRange(listOfdeliveries.ToArray());
//...
if (ViewListBox.SelectedIndex < listOfPickups.Count)
{
// this is a Pickup
visits.removePickup(ViewListBox.SelectedIndex);
}
else
{
// this is a delivery
int deliveryIndex = ViewListBox.SelectedIndex - listOfPickups.Count;
visits.removeDelivery(deliveryIndex);
}
First of all, I'm using Visual Studio 2010 (Visual C#) and ASP.NET.
I'm working with a GridView that displays the current open positions at my company. I have a column of checkboxes where applicants can check off the position(s) for which they want to apply. To eliminate duplicate data, I created a linking table between my three main tables (POSITION, APPLICANT, and APPLICATION). It's made up of just the primary keys from each of those tables, so if one person applies for 3 positions, we won't have 3 whole applications to sift through.
I need to select the PositionID's of the positions they selected and store them in session variables for later use.
My question is, how do I do that without knowing how many they have checked? I don't want to just create a bunch of unnecessary variables that won't be used. I figure I'll have to use a foreach loop, but within the loop, I don't know how to tell it to create a new session variable and store the ID in it.
I sure hope this question makes sense. If you need clarification, let me know.
You can just create a List<int> or whatever datatype PositionID is and store that in the session variable.
In fact, I would create a property in the control or page as
public List<int> SelectedPositionIDList
{
get
{
if(Session["SelectedPositions"] != null)
return Session["SelectedPositions"] as List<int>;
return new List<int>();
}
set
{
Session["SelectedPositions"] = value;
}
}
you can iterate through the list of position ids as ,
foreach(int positionId in SelectedPositionIdList)
{
//Do something.
}
Of course, you need to grab the ids from the gridview when they want to save, or do some action. You can probably do that by looping through the gridview rows based on your implementation. Something like below.
List<int> positions = new List<int>();
foreach(GridviewRow row in gdPositions)
{
CheckBox cb = row.FindControl("checkbox") as CheckBox;
if(cb != null && cb.Checked)
positions.Add(/*find position id from row here*/);
}
if(positions.Count > 0)
Session["SelectedPositionIdList"] = positions;
I have a form containing many picture boxes named pb_a1,pb_a2,pb_a3... and so on..
I have a String array containing the picture box names. What I need to do is access each of these and specify an image for it.
Instead of hard coding, I would like to know if there is any way by which I can write a loop which gives me commands like
> Form1.pb_a1.Image=<some Image>;
>
> Form1.pb_a2.Image=<some Image>;
>
> Form1.pb_a3.Image=<some Image>;
>
> Form1.pb_a4.Image=<some Image>;
Can you use the ControlCollection.Find( ) method on the forms Controls property?
if you only have the name of the picture controls and not a reference to them ( which I think you could have kept in a dictionary with name and reference when you created those controls earlier in the form... ), the only way you have I think is to search in the Form.Controls collection until you find the one with the name you are looking for and which is of the picture box type.
You're better off storing the picture boxes in a picture box array, rather than a string array.
PictureBox[] myPictures = {pictureBox1, pictureBox2, pictureBox3, pictureBox4};
foreach (PictureBox picture in myPictures)
{
picture.Image = <some Image>;
}
If you have to have it as a string, the following code may help you out. Please note that I haven't included any error checking incase the element doesn't exist. You're likely to just get an empty element in that part of the array. You may want to encase it in try/catch as well.
string[] myPicturesString = {"pictureBox1", "pictureBox2", "pictureBox3", "pictureBox4"};
PictureBox[] myPictures = new PictureBox[myPicturesString.Length];
for (int i = 0; i < myPictures.Length; i++)
{
foreach (Control c in this.Controls)
{
if (c.Name == myPicturesString[i])
{
myPictures[i] = (PictureBox) c;
}
}
}
MessageBox.Show(myPictures[1].Name);
Assuming that these picturebox are fields of your form, you can reflect (System.Reflection) on the form class, retrieve a reference to the picturebox fields and store them into a dictionary. Do that during form creation (after InitializeComponent).
Next time you have to access a picture box by its name, just use:
myDictionary["pictureboxname"].Image = blabla;