Remove duplicates entries from the ListView in form c# - c#

I have a set of code which lists the users details in a list view from a database, it works however multiple entries are often added in when the user clicks to register. How can i get it to work so that the listview knows the name is already present and stops adding mutliple entries into the listview?
this is the code i have for the list view:
listView1.View = View.Details;
var item = new ListViewItem();
item.Text = reader["SSN"].ToString(); // 1st column text
item.SubItems.Add(reader["FirstName"].ToString());// 2nd column text
item.SubItems.Add(reader["LastName"].ToString());// 3rd column text
listView1.Items.Add(item);

You should check manually duplicate entries before adding:
if(!listView1.Items.ContainsKey(stringToInsert))
{
listView1.Items.Add(stringToInsert);
}

If you are loading these from a database you should have a primary key value of sorts, even if it's a mere incremental integer value.
While your ListView can contain ListViewItem populated from your database, it would be wise to store the actual data models themselves in a collection. I would suggest a Dictionary for this, and it would be relatively simple to check for duplicates this way.
For example:
class UserModel
{
public int Id { get; set; }
public string SSN { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Then in your Form, you could have a member variable like so:
Dictionary<int, UserModel> users = new Dictionary<int, UserModel>();
void AddItemToList(UserModel model)
{
if(users.ContainsKey(model.Id)) return; // avoid duplicates
var listViewItem = new ListViewItem();
listViewItem.Text = model.SSN;
listViewItem.SubItems.Add(model.FirstName);
listViewItem.SubItems.Add(model.LastName);
listView.Items.Add(listViewItem);
}
In addition, you should be loading your UserModel from the database.

Related

Add Tag to ComboBox Items From Model

I have a TypeOfContact model that is made up of an ID, and Text. For example, one type would be Telephone and the ID would be 1. Another type would be Email and the ID 2.
What I would like to do is add the text of the TypeOfContact as an item and the ID as a tag. I imagine it would look something like this, however this isn't working;
contactTypeComboBox.Items.Clear();
foreach (TypeOfContact c in ContactTypes)
{
contactTypeComboBox.Items.Add(c.ContactTypeText);
foreach (ComboBoxItem item in contactTypeComboBox.Items)
{
item.Tag = c.ContactTypeID;
}
}
The reason I want to do this is that when someone selects one of the ComboBox items I want to store the text and the ID. I could do this all through XAML but ContactTypes is a list that is populated by the user, so I cannot hard code the values into the ComboBox as maintaining it and adding new TypesOfContact would be difficult.
I fixed this issue myself by first adding;
DisplayMemberPath="ContactTypeText" SelectedValuePath="ContactTypeID"
to the XAML of the ComboBox then accessing the ID like;
contactTypeComboBox.SelectedValue
In your situation i would bind the list of your TypeOfContacts as ItemsSource to the ComboBox. After that you could set the tag, but i think you don't will need it, because when you also bind the SelectedItem you got back the whole item (ID, type, ...) and can work with it in other parts of your code.
Example for simplifying without a ViewModel (but you should use one):
Codebehind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
FillListWithSomeExamples();
}
private void FillListWithSomeExamples()
{
TypesOfContacts.Add(new TypesOfContact {Id = 1, Type = "Email"});
TypesOfContacts.Add(new TypesOfContact { Id = 2, Type = "Telephone" });
}
public TypesOfContact SelectedTypesOfContact { get; set; }
public ObservableCollection<TypesOfContact> TypesOfContacts { get; set; } = new ObservableCollection<TypesOfContact>();
}
TheTestmodel:
public class TypesOfContact
{
public int Id { get; set; }
public string Type { get; set; }
}
XAML
<Grid>
<ComboBox ItemsSource="{Binding TypesOfContacts}" SelectedItem="{Binding SelectedTypesOfContact}" DisplayMemberPath="Type"/>
</Grid>
Now you can read the selected item in any other method of the MainWindow by looking at SelectedTypesOfContact.

Not updating database

I have the following two classes generated by Entity Framework..
public partial class Datagrid
{
public int Id { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public Nullable<bool> IsChecked { get; set; }
}
public partial class SampleDbContext : DbContext
{
public SampleDbContext()
: base("name=SampleDbContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Datagrid> Datagrids { get; set; }
}
i have a WPF application where I have a list view containing checkboxs for each column.. I have written the to logic to find what are the checkboxes that are checked in the list view.. But when I iterate through the checked boxes and try to save to the database, database is not updating please help..
dg is object of type Datagrid..
db is object of type SampleDbContext
foreach (CheckBox cb in myBoxes)
{
dg.IsChecked = cb.IsChecked; //I want to update each column with the checked value in the listview. cb.Ischecked works perfectly..It says true for the checkboxes that are checked else false
db.SaveChanges(); //NOT updating the database
}
Your variable 'dg' will need to be part of the databaseContext's ('db' in your code) DataGrid's Property. An example:
foreach (CheckBox cb in myBoxes)
{
dg.IsChecked = cb.IsChecked;
db.DataGrids.Add(dg);
db.SaveChanges();
}
.SaveChanges() will only flush items assigned to the DataGrid property to the database.
Based on your comments, I'm not entirely clear on if the checkboxes need to be created each time or just updated. If created, it will be somewhat like the other answer. However, you were likely getting the System.Data.Entity.Validation.DbEntityValidationException due to attempting to add a new Datagrid without providing a Name and Location, which are not nullable and are not (presumably) automatically populated like Id:
foreach (CheckBox cb in myBoxes)
{
Datagrid dg = new Datagrid
{
Name = "NameGoesHere"; // Maybe you're wanting to use cb.Name or cb.Text?
Location = "Location Here";
IsChecked = cb.IsChecked;
};
db.DataGrids.Add(dg);
db.SaveChanges();
}
If you're just updating instead, I'm still not sure where you're setting dg, but perhaps you might want to look it up from :
foreach (CheckBox cb in myBoxes)
{
Datagrid dg = db.DataGrids.Where(g => g.Name == cb.Name).SingleOrDefault();
// etc.
Edit based on comments:
If you're doing two-way binding and have directly bound CheckBoxes to the IsChecked values of Datagrid entities, you shouldn't need to do anything other than simply call db.SaveChanges(); when you're ready to save. The bound Datagrid entities will be updated on their own.

DataGridView doesn't update Enum in BindingList

The DataSource of my DataGridView is a BindingList<Filter> which contains an enum. The gridview contains only two columns: a regular textbox column for a string, and a combobox (drop down) column for the enum. If I bind the combobox column to the enum variable of my object I get an error. Here is the code for my objects:
public class FilterProfile
{
public FilterProfile()
{
filters = new BindingList<Filter>(); // the list that gets bound to gridview
}
public string name { get; set; }
public BindingList<Filter> filters { get; set; }
}
public class Filter
{
public string keyword { get; set; }
public FilterType type { get; set; } // the enum in question
}
public enum FilterType : int
{
SESSION = 1,
ORDER = 2,
SHIPMENT = 3
}
I have a form where the user selects a FilterProfile from a dropdown menu and then I find the appropriate FilterProfile from a global list and bind it:
foreach (PlvFilterProfile filterProfile in _filterProfiles)
{
// find the correct filter profile
if (filterProfile.name.Equals(lstFilterProfiles.Text))
{
// bind it
grdFilters.DataSource = filterProfile.filters;
break;
}
}
In order for the changes made in the DataGridView to be reflected in filterProfile.filters I need to set the DataPropertyName attribute of both columns to their respective variable (either keyword or type). This works correctly for the keyword string, but not with the type enum.
If I keep the line colFilterType.DataPropertyName = "type"; I get the error below whenever a new row is created or whenever I put my mouse over the dropdown. If I get rid of it, the type of every newly created Filter is set to 0 and never updated.
I'm not sure what causes the DataError event so don't know how to handle it or where to breakpoint.
The problem is when you focus on the new row (prepare to add a new row), a new object is required in the underlying list, this object is default by null, that value is bound to the new row and of course the ComboBoxCell can't accept that null value, causing the exception as you encountered. The solution is very simple indeed, we just need to handle the event AddingNew of the BindingList, set the default new object in there to a valid value and then it works just fine:
public FilterProfile()
{
filters = new BindingList<Filter>(); // the list that gets bound to gridview
filters.AddingNew += (s,e) => {
//the default value of FilterType is up to you.
e.NewObject = new Filter {type = FilterType.SESSION };
};
}

Using 2 maps on the same source?

I have 2 maps that I want to throw into the same source. But it seems one source overrides the second source even though I am targeting different fields.
public class FormViewModel
{
public List<SelectListItem> Items { get; set; }
public string SelectedItem { get; set; }
public string SomeField {get; set;}
// I have many more
}
List<Items> items = Service.GetItems();
FormViewModel viewModel = new FormViewModel()
{
Items = Mapper.Map<List<Items>, List<SelectListItem>>(courses);
};
var fields = Service.GetFields();
viewModel = Mapper.Map<Fields, FormViewModel>(fields);
So now when I do the second map. It will wipe out my first map. How can I stop this?
Edit
I guess I can see why it is happening. I thought it was just filling in those the fields but now I am looking at it and seeing that it is return a new FormViewModel.
I guess I can rearrange my code so that I first do the last map first then add my other map after.
List<CalendarAppointmentReminderVM> vm = Mapper.Map<List<CalendarAppointment>, List<CalendarAppointmentReminderVM>>(taskReminders.Select(x => x.CalendarAppointment).ToList());
Mapper.Map<List<AppointmentReminder>, List<CalendarAppointmentReminderVM>>(taskReminders, vm);
Separately they work. But together the first result gets wiped out by the first one.
pass the output of the first mapping into the second mapping so it doesn't create a new one...
viewModel = Mapper.Map<Fields, FormViewModel>(fields, viewModel);

Need to change selected item in dropdown list when selected item in another dropdown list changes

I have a windows form application with two Combo boxes (Dropdownlist style). The first combo box gets the data from a List of AppTable object, like so:
foreach (AppTable table in appTableList)
cbxSelectName.Items.Add(table.App);
I have set up a trigger for when the selected item in this dropdown is changed:
this.cbxSelectName.SelectedIndexChanged +=new EventHandler(cbxSelectName_SelectedIndexChanged);
And finally, here is the definition of the method the trigger calls. Please note, the value in tbxNewWikiWord textbox changes as the selected item is changed. However, the same does not happen in the second dropdown list ( cbxUpdateAppType):
private void cbxSelectName_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (AppTable table in appTableList)
{
if (table.App == cbxSelectName.SelectedItem.ToString())
{
this.tbxNewWikiWord.Text = table.WikiWord;
this.cbxUpdateAppType.SelectedItem = table.Type;
break;
}
}
}
This is how AppTable looks:
class AppTable
{
public string App { get; set; }
public string Type { get; set; }
public string WikiWord { get; set; }
}
Am I missing something?
Adding values to cbxUpdateAppType from the AppTable object fixed it. I'm not sure why since in either case, I was adding Strings.
I just needed to check for duplicates so I don't end up with multiple instances of the same value in my dropdown box.
foreach (AppTable table in appTableList)
{
if (!cbxUpdateAppType.Items.Contains(table.Type))
cbxUpdateAppType.Items.Add(table.Type);
}

Categories

Resources