Finding names in List - c#

I am new to programming and to this forum. I have searched the forum for answers but havent found anything that works for me. I have created a adressbook in WinForms with a search function. The search finds the the specified contact, but when I click on the contact the information it loads belongs to the first contact in the List. This happens for every contact in the list exept for the first contact.
var TempVar = People.Where(a => a.Namn.ToLower().Contains(txtSearchbar.Text.ToLower()) ||
a.PostOrt.ToLower().Contains(txtSearchbar.Text.ToLower())).ToList();
foreach (var item in TempVar)
{
ListBoxOne.Items.Add(TempVar);
}
Tell me if you need more information. Thanks for all the help!!
EDIT1:
Dont know if this is the right way to answer, but the comment section didnt let me post a long answer.
For starters. Thanks for being so helpful. I tried your code for adding to the list, but got the errorcode: Cannot convert System.Collecion.Generic.List to System.Windows.Forms.ListBox.ObjectCollection. Searched the web for a solution but came up short. Shall I post my entire code? Also tried your search code it works great. But my main problem is still there. When I click on the search results the name in the listbox shows the contact information of the first contact in the entire contactlist. Its as if the index of the contacts is still in the listbox but when contacts in the Listbox are sorted out by the search function the first contacts index is given to the contact the search found. Shall I post my entire code to make everything clearer.? Thanks for all the help!
EDIT2: Here is the code. I got a class with person propertys. Name, adress, postnummber, city, telephone annd email that links to the list.
I know some of the comments are in swedish and it is a hassle. Ask me if there is anything you donte understand.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
List<Person> People = new List<Person>();//Skapar en lista med alla variabler i Person
private void Form1_Load(object sender, EventArgs e)//Reads file on start up.
{
//string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
if (Directory.Exists("C:\\visualFolder\\Adressbok"))
{
Directory.CreateDirectory("C:\\visualFolder\\Adressbok");
}
if (!File.Exists("C:\\visualFolder\\Adressbok\\settings.xml"))
{
XmlTextWriter XW = new XmlTextWriter("C:\\visualFolder\\Adressbok\\settings.xml", Encoding.UTF8);
XW.WriteStartElement("People");
XW.WriteEndElement();
XW.Close();
}
XmlDocument xDoc = new XmlDocument();
xDoc.Load("C:\\visualFolder\\Adressbok\\settings.xml");
foreach (XmlNode XNode in xDoc.SelectNodes("People/Person"))
{
Person p = new Person();
p.Namn = XNode.SelectSingleNode("Namn").InnerText;
p.GatuAdress = XNode.SelectSingleNode("Adress").InnerText;
p.PostNummer = XNode.SelectSingleNode("Postnummer").InnerText;
p.PostOrt = XNode.SelectSingleNode("Postort").InnerText;
p.Telefon = XNode.SelectSingleNode("Telefon").InnerText;
p.Email = XNode.SelectSingleNode("Email").InnerText;
People.Add(p);
ListBoxOne.Items.Add(p.Namn);
}
}//----
private void cmdRegistrera_Click(object sender, EventArgs e)//Adds contact
{
Person LäggTillPerson = new Person();
LäggTillPerson.Namn = txtNamn.Text;
LäggTillPerson.GatuAdress = txtAdressText.Text;
LäggTillPerson.PostNummer = txtPostNummer.Text;
LäggTillPerson.PostOrt = txtPostOrt.Text;
LäggTillPerson.Telefon = txtTelefonnummer.Text;
LäggTillPerson.Email = txtEpost.Text;
People.Add(LäggTillPerson);
ListBoxOne.Items.Add(LäggTillPerson.Namn);
txtNamn.Clear();
txtAdressText.Clear();
txtPostNummer.Clear();
txtPostOrt.Clear();
txtTelefonnummer.Clear();
txtEpost.Clear();
}
private void cmdTaBort_Click(object sender, EventArgs e)//Deletes contact.
{
if (ListBoxOne.SelectedItem != null)
{
People.RemoveAt(ListBoxOne.SelectedIndex);
ListBoxOne.Items.Remove(ListBoxOne.SelectedItems[0]);
}
txtNamn.Clear();
txtAdressText.Clear();
txtPostNummer.Clear();
txtPostOrt.Clear();
txtTelefonnummer.Clear();
txtEpost.Clear();
}
private void ListboxOne_SelectedIndexChanged(object sender, EventArgs e)//
{
if (ListBoxOne.SelectedItem != null)
{
txtNamn.Text = People[ListBoxOne.SelectedIndex].Namn;
txtAdressText.Text = People[ListBoxOne.SelectedIndex].GatuAdress;
txtPostNummer.Text = People[ListBoxOne.SelectedIndex].PostNummer;
txtPostOrt.Text = People[ListBoxOne.SelectedIndex].PostOrt;
txtTelefonnummer.Text = People[ListBoxOne.SelectedIndex].Telefon;
txtEpost.Text = People[ListBoxOne.SelectedIndex].Email;
}
}
private void cmdSpara_Click(object sender, EventArgs e)//Saves changes.
{
if (ListBoxOne.SelectedItem != null)
{
People[ListBoxOne.SelectedIndex].Namn = txtNamn.Text;
People[ListBoxOne.SelectedIndex].GatuAdress = txtAdressText.Text;
People[ListBoxOne.SelectedIndex].PostNummer = txtPostNummer.Text;
People[ListBoxOne.SelectedIndex].PostOrt = txtPostOrt.Text;
People[ListBoxOne.SelectedIndex].Telefon = txtTelefonnummer.Text;
People[ListBoxOne.SelectedIndex].Email = txtEpost.Text;
ListBoxOne.Items.Clear();
foreach (var item in People)
{
ListBoxOne.Items.Add(item.Namn);
}
}
MessageBox.Show("Ändringarna är sparade");
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)//Saves to file on when closin the application.
{
XmlDocument xDoc = new XmlDocument();
xDoc.Load("C:\\visualFolder\\Adressbok\\settings.xml");
XmlNode xNode = xDoc.SelectSingleNode("People");
xNode.RemoveAll();
foreach (Person p in People)
{
XmlNode xTop = xDoc.CreateElement("Person");
XmlNode Xnamn = xDoc.CreateElement("Namn");
XmlNode Xadress = xDoc.CreateElement("Adress");
XmlNode XPostnummer = xDoc.CreateElement("Postnummer");
XmlNode XpostOrt= xDoc.CreateElement("Postort");
XmlNode Xtelefon = xDoc.CreateElement("Telefon");
XmlNode XeMAil = xDoc.CreateElement("Email");
Xnamn.InnerText = p.Namn;
Xadress.InnerText = p.GatuAdress;
XPostnummer.InnerText = p.PostNummer;
XpostOrt.InnerText = p.PostOrt;
Xtelefon.InnerText = p.Telefon;
XeMAil.InnerText = p.Email;
xTop.AppendChild(Xnamn);
xTop.AppendChild(Xadress);
xTop.AppendChild(XPostnummer);
xTop.AppendChild(XpostOrt);
xTop.AppendChild(Xtelefon);
xTop.AppendChild(XeMAil);
xDoc.DocumentElement.AppendChild(xTop);
}
xDoc.Save("C:\\visualFolder\\Adressbok\\settings.xml");
}
private void cmdSök_Click(object sender, EventArgs e)//Search function. This is where the problem is.
{
if (txtSearchbar.Text != "")
{
var term = txtSearchbar.Text;
var results = People.Where(a => ContainsCI(a.Namn, term)
|| ContainsCI(a.PostOrt, term));
foreach (var item in results)
{
ListBoxOne.Items.Add(item);
}
ListBoxOne.Items.Clear();
foreach (var item in results)
{
ListBoxOne.Items.Add(item.Namn);
}
txtSearchbar.Clear();
}
else
{
ListBoxOne.Items.Clear();
foreach (var item in People)
{
ListBoxOne.Items.Add(item.Namn);
}
}
}
private void cmdClearSearch_Click(object sender, EventArgs e)//Clears the searchebar and ListBox and loads the contacts again.
{
ListBoxOne.Items.Clear();
txtSearchbar.Clear();
foreach (var item in People)
{
ListBoxOne.Items.Add(item.Namn);
}
txtNamn.Clear();
txtAdressText.Clear();
txtPostNummer.Clear();
txtPostOrt.Clear();
txtTelefonnummer.Clear();
txtEpost.Clear();
}
public bool ContainsCI(string input, string term)//Search function. courtesy of Panagiotis Kanavos
{
if (String.IsNullOrWhiteSpace(input))
{
return false;
}
//Returns true even if `terms` is empty, just like String.Contains
return input.IndexOf(term, StringComparison.CurrentCultureIgnoreCase) != -1;
}
}
}

Your code has a typo. Instead of adding individual items you keep adding the list itself to the listbox. You should add the individual items:
foreach (var item in TempVar)
{
ListBoxOne.Items.Add(item);
}
A better option though would be to use AddRange to add the entire list at once:
ListBoxOne.Items.AddRange(TempVar);
You can improve the rest of the code as well. Instead of Contains which is case sensitive, you can use IndexOf with a case-insensitive StringComparison parameter. To make the code a bit cleaner, I created a separate ContainsCI method:
public bool ContainsCI(string input, string term)
{
if (String.IsNullOrWhitespace(input))
{
return false;
}
//Returns true even if `terms` is empty, just like String.Contains
return input.IndexOf(term,StringComparison.CurrentCultureIgnoreCase)!= -1);
}
...
var term=txtSearchbar.Text;
var results= People.Where(a => ContainsCI(a.Namn, term)
|| ContainsCI(a.PostOrt,term));
ListBoxOne.Items.AddRange(results);
By using IndexOf instead of Contains and ToLower() the code avoids generating temporary strings which end up wasting memory for no gain.
Note that both String.Contains and ContainsCI return true if the term is empty. This makes it easy to return all items if the search box is empty.

Related

elastic search field update from csv file in c#

I am new to programming in C#
I want to read the csv file and update the fields in elastic search. I already have this function made by someone else and I want to call this function and update fields.
public static bool UpdateDocumentFields(dynamic updatedFields, IHit<ClientDocuments> metaData)
{
var settings = (SystemWideSettings)SystemSettings.Instance;
if (settings == null)
throw new SettingsNotFoundException("System settings have not been initialized.");
if (ElasticSearch.Connect(settings.ElasticAddressString(), null, out ElasticClient elasticClient, out string status))
{
return ElasticSearch.UpdateDocumentFields(updatedFields, metaData, elasticClient);
}
return false;
}
what I have done myself so far is :
private void btnToEs_Click(object sender, EventArgs e)
{
var manager = new StateOne.FileProcessing.DocumentManager.DocumentManager();
var path = "C:/Temp/MissingElasticSearchRecords.csv";
var lines = File.ReadLines(path);
foreach (string line in lines)
{
var item = ClientDocuments.GetClientDocumentFromFilename(line);
if (item != null)
{
var output = new List<ClientDocuments>();
manager.TryGetClientDocuments(item.AccountNumber.ToString(), 100, out output);
if (output!= null && output.Count <= 0)
{
var docs = new List<ClientDocuments>();
//var doc = docs.Add();
// var doc = docs.Add();
//docs.Add(doc);
foreach (var doc in output)
{
if (!item.FileExists)
{
//insert in elastic search
manager.UpdateDocumentFields(output, );
}
else
{
//ignore
}
}
My problem here is manager.updateDocumentFields() is a function. I am calling it but what I need to pass as a parameter? Thanks in advance.

How to use AutoSuggest from a DataBase in a textbox?

I'm trying to display name suggestions on a textbox but it's not suggesting anything. I followed a couple tutorials about this but still with the exact same code I cant make it work. I'm using Dapper so maybe I have done something wrong there. Am I missing something?
This is what I have done with Dapper:
public static List<string> DevolverNombres()
{
var dbCon = DBConnection.Instancia();
if (dbCon.Conectado())
{
using (IDbConnection conexion = dbCon.Conexion)
{
var output = conexion.Query($"SELECT nombre FROM usuario;").ToList();
var lista = new List<string>();
foreach (IDictionary<string, object> row in output)
{
foreach (var pair in row)
{
lista.Add(pair.Value.ToString());
}
}
return lista;
}
}
else return null;
}
And this is what I have in the form:
private void Home_Load(object sender, EventArgs e) {
var nombres = AccesoDatos.DevolverNombres();
var lista = new AutoCompleteStringCollection();
foreach(string elem in nombres)
{
lista.Add(elem);
}
txtBuscar.AutoCompleteCustomSource = lista;
}

Programmatic filtering RadGridView

Let's say that in my db, in a column named UserName, i have this value Jean-Andrew Pierre. I have a problem with creating the filter for retrieving this value from db, when i'm typing Andrew Jean Pierre. As you see, the order of names, are different and some characters are missing.
I've tried this:
var operatorNameFilter = radGridView.Columns[nameof(Username)].ColumnFilterDescriptor;
if (string.IsNullOrEmpty(username))
{
operatorNameFilter.Clear();
return;
}
allOperatorsName = Regex.Split(username, #"\W+");
foreach (var name in allOperatorsName)
operatorNameFilter.DistinctFilter.AddDistinctValue(name);
operatorNameFilter.FieldFilter.Filter1.Operator = FilterOperator.Contains;
operatorNameFilter.FieldFilter.Filter1.LogicalOperator = FilterCompositionLogicalOperator.And;
operatorNameFilter.FieldFilter.Filter1.Value = username;
I believe the last line has to be removed, but with or without, nothing happen
Thanks,
Andreea
I found an answer after few more tries:
private void FilterByOperatorNames(RadGridView radGridView)
{
var operatorNameFilter = radGridView.Columns[nameof(Username)].ColumnFilterDescriptor;
if (string.IsNullOrEmpty(username))
{
operatorNameFilter.Clear();
return;
}
var allOperatorNames = Regex.Split(username, #"\W+");
var userNamesCompositeFilter = new CompositeFilterDescriptor();
foreach (var name in allOperatorNames)
{
var filterDescriptor = new FilterDescriptor(nameof(Username), FilterOperator.Contains, name);
userNamesCompositeFilter.FilterDescriptors.Add(filterDescriptor);
}
userNamesCompositeFilter.LogicalOperator = FilterCompositionLogicalOperator.And;
radGridView.FilterDescriptors.Add(userNamesCompositeFilter);
}
I hope to help others.

C# Creating a datasource that gets all branches for a specific bank

I am trying to create a binding source to my binding navigator that will be able to show all branches within a specific bank.
The statement that gets the datasource is as follows
branchMasterBindingSource.DataSource = Program.Kernel.Get<IBranchMasterService>().GetAllBranchMasters();
However, this pulls all branches regardless of the banks they belong to.
I need to know how to change this so that it gets AllBranchMasters where a field in the database ("U_bank_code") is equals to a combobox named "cb_bank_code"
Extra code is below:
private void cb_bank_code_SelectedIndexChanged(object sender, EventArgs e)
{
branchMasterBindingSource.DataSource = null;
branchMasterBindingSource.DataSource = Program.Kernel.Get<IBranchMasterService>().GetAllBranchMasters();
//clear textfields after input
lbl_show_bank_name.Text = string.Empty;
txt_branch_code.Text = string.Empty;
txt_branch_name.Text = string.Empty;
txt_swift_sort_code.Text = string.Empty;
txt_address_1.Text = string.Empty;
txt_address_2.Text = string.Empty;
txt_comments.Text = string.Empty;
var bankMasterService = Program.Kernel.Get<IBankMasterService>();
var bankMasters = from bm in bankMasterService.GetAllBankMasters()
where bm.U_Bank_code.Trim().Equals(cb_bank_code.Text.Trim(), StringComparison.CurrentCultureIgnoreCase)
select bm;
if (bankMasters.Any(x => x != null))
{
var bankMaster = bankMasters.First();
lbl_show_bank_name.Text = bankMaster.U_Bank_name;
CbBankCode = bankMaster.U_Bank_code;
}
else
{
//clear textfields after input
lbl_show_bank_name.Text = string.Empty;
}
Im new to C# and dot net and do not know how the syntax to change the statement. Any help appreciated
If I understand you correctly, and make a couple assumptions on the types, the following should work:
branchMasterBindingSource.DataSource = Program.Kernel.Get<IBranchMasterService>().GetAllBranchMasters.Where(x => x.U_Bank_code.Trim().Equals(cb_bank_code.Text.Trim(), StringComparison.CurrentCultureIgnoreCase))
I'm guessing the
Program.Kernel.Get<IBranchMasterService>().GetAllBranchMasters
returns an IEnumerable or perhaps List. There won't be much you can do about that function returning all banks/branches unless you either:
Change GetAllBranchMasters to return an IQueryable - you can then apply the filter as above and add .ToList() to the end to perform the query.
(Recommended) Create a second method that accepts a Bank Code, and returns the branches in accordance with the underlying DAL.
Although you should look at refactoring your data access methods to do the filtering something like this should do the trick for you
private void cb_bank_code_SelectedIndexChanged(object sender, EventArgs e)
{
ClearTextfieldsAfterInput();
branchMasterBindingSource.DataSource = GetSelectedBranchMasters();
var bankMasters = GetSelectedBankMaster();
if (bankMasters.Any(x => x != null))
{
var bankMaster = bankMasters.First();
lbl_show_bank_name.Text = bankMaster.U_Bank_name;
CbBankCode = bankMaster.U_Bank_code;
}
else
{
//clear textfields after input
lbl_show_bank_name.Text = string.Empty;
}
}
private IEnumerable<BankMaster> GetSelectedBankMaster()
{
var selectedBank = cb_bank_code.Text.Trim();
return Program.Kernel.Get<IBankMasterService>()
.GetAllBankMasters()
.Where(bm => bm.U_Bank_code.Trim().Equals(selectedBank, StringComparison.CurrentCultureIgnoreCase))
.ToList();
}
private IEnumerable<BranchMaster> GetSelectedBranchMasters()
{
var selectedBank = cb_bank_code.Text.Trim();
return Program.Kernel.Get<IBranchMasterService>()
.GetAllBranchMasters()
.Where(branch => string.Equals(branch.U_bank_code, selectedBank, StringComparison.CurrentCultureIgnoreCase))
.ToList();
}
private void ClearTextfieldsAfterInput()
{
lbl_show_bank_name.Text = "";
txt_branch_code.Text = "";
txt_branch_name.Text = "";
txt_swift_sort_code.Text = "";
txt_address_1.Text = "";
txt_address_2.Text = "";
txt_comments.Text = "";
}

Dynamic Data Custom Field Template updating a list

I have a website using dynamic data and linq to sql. This website runs 3 'subsites' and has a list of categories with a many to many relationship.
I have 3 tables and hence 3 objects in my dbml; Website, Categories, and CategoriesToWebsites
What I am trying to do is create a field template such that on my Categories/Edit.aspx page I can edit a category and specify which website the category belongs in.
The field template is CategoriesToWebsites_Edit.ascx, which is basically a checkbox list bound to the list of websites.
Code below:
public partial class CategoriesToWebsitesEdit : FieldTemplateUserControl
{
protected override void OnLoad(EventArgs e)
{
var dataSource = (LinqDataSource)this.FindDataSourceControl();
dataSource.Inserting += OnInserting;
dataSource.Updating += OnUpdating;
}
private void OnUpdating(object sender, LinqDataSourceUpdateEventArgs e)
{
var newCategory = (Category)e.NewObject;
var oldCategory = (Category)e.OriginalObject;
foreach(var listItem in WebsiteList.Items.Cast<ListItem>())
{
//check if website category already exists
var categoryToWebsite = oldCategory.CategoriesToWebsites.FirstOrDefault(x => x.WebsiteId == Convert.ToInt32(listItem.Value));
//website category exists
if (categoryToWebsite != null)
{
// check if selected for removal, remove
if (!listItem.Selected)
{
newCategory.CategoriesToWebsites.Remove(categoryToWebsite);
}
}
//we want to insert
if (listItem.Selected)
{
//website category does not exist, add
if (categoryToWebsite == null)
{
//add selected website if not already exists
newCategory.CategoriesToWebsites.Add(new CategoriesToWebsite
{
WebsiteId = Convert.ToInt32(listItem.Value)
});
}
}
}
}
private void OnInserting(object sender, LinqDataSourceInsertEventArgs e)
{
var category = (Category)e.NewObject;
foreach(var listItem in WebsiteList.Items.Cast<ListItem>())
{
if(!listItem.Selected)
continue;
category.CategoriesToWebsites.Add(new CategoriesToWebsite
{
WebsiteId = Convert.ToInt32(listItem.Value)
});
}
}
protected override void OnDataBinding(EventArgs e)
{
var websiteRepository = new WebsiteRepository();
var websites = websiteRepository.GetAll();
var websiteCategories = (IEnumerable<CategoriesToWebsite>)FieldValue;
foreach(var website in websites)
{
var currentWebsite = website;
var listItem = new ListItem(website.Name, website.Id.ToString())
{
Selected = websiteCategories == null ? false : websiteCategories.Any(w => w.WebsiteId == currentWebsite.Id)
};
WebsiteList.Items.Add(listItem);
}
}
}
When I go to Categories/Insert.aspx to create a new category, it runs through the OnInserting code fine and saves it to db just fine, everything seems to be working here.
On Categories/Edit.aspx it goes through the code just as I expect, but does not seem to save anything.
What am I missing? - I'm not too familiar with Dynamic Data Field Templates so any guidance will be much appreciated
Apparently I was going about this slightly wrong. I was simply updating the object in the linq data source, which wasn't being saved. So instead I go straight to the repository:
private void OnUpdating(object sender, LinqDataSourceUpdateEventArgs e)
{
var newCategory = (Category)e.NewObject;
var oldCategory = (Category)e.OriginalObject;
var repository = new Repository<CategoriesToWebsite>();
var ctw = repository.GetAll().Where(x => x.CategoryId == newCategory.Id);
foreach (var listItem in WebsiteList.Items.Cast<ListItem>())
{
var current = ctw.FirstOrDefault(x => x.WebsiteId == Convert.ToInt32(listItem.Value));
//current categoriesToWebsite exists
if (current != null)
{
//if not selected, remove
if (!listItem.Selected)
repository.Delete(current);
}
//does not exist
else
{
//if selected, add
if (listItem.Selected)
repository.Save(new CategoriesToWebsite()
{
CategoryId = newCategory.Id,
WebsiteId = Convert.ToInt32(listItem.Value)
}
);
}
}
UnitOfWork.Current.SubmitChanges();
}
I'm not sure if this is the proper way to do this since the field template here is doing some updating directly to the db. But it works.

Categories