C# web browser history - c#

I'm developing a web browser in C# using Visual Studio 2017. I am trying to save the user's search history in a database and display it in a listbox. However, the database and listbox are empty. I have no idea why it's not working.
I have a bookmark button that works in the same way. It functions fine. The bookmarks show up in the listbox.
Any thoughts as to why the history listbox is always empty?
public class HistoryItem
{
public string URL { get; set; }
public string Title { get; set; }
public DateTime Date { get; set; }
public int Id { get; set; }
}
public static void AddItem(HistoryItem item)
{
var adapter = new HistoryTableAdapter();
adapter.Insert(item.URL, item.Title, item.Date.ToShortDateString());
}
public static List<HistoryItem> GetItems()
{
var adapter = new HistoryTableAdapter();
var results = new List<HistoryItem>();
var rows = adapter.GetData();
foreach (var row in rows)
{
var item = new HistoryItem();
item.URL = row.URL;
item.Title = row.Title;
item.Date = DateTime.Parse(row.Date);
item.Id = row.Id;
results.Add(item);
}
return results;
}
private void DisplayLabel(object sender, WebBrowserDocumentCompletedEventArgs e)
{
toolStripStatusLabel1.Text = "Done";
toolStripProgressBar1.Value = 0;
var item = new HistoryItem();
item.URL = toolStripTextBox1.Text;
item.Title = webBrowser1.DocumentTitle;
item.Date = DateTime.Now;
HistoryManager.AddItem(item);
}
private void HistoryManager_Load(object sender, EventArts e)
{
var items = HistoryManager.GetItems();
foreach (var item in items)
{
HistoryListBox.Items.Add(string.Format("{0} ({1}) [{2}]", item.Title, item.URL, item.Date));
}
}

Related

c# how to access all instances of a class outside of the function?

I am new to C# and OOP, in general, I've kinda hit a wall I am reading in this CSV using the CSV Helper package, but there are some unwanted rows, etc so I have cleaned it up by iterating over "records" and creating a new class LineItems.
But Now I appear to be a bit stuck. I know void doesn't return anything and is a bit of a placeholder. But How can I access all the instances of LineItems outside of this function?
public void getMapper()
{
using (var StreamReader = new StreamReader(#"D:\Data\Projects\dictUnitMapper.csv"))
{
using (var CsvReader = new CsvReader(StreamReader, CultureInfo.InvariantCulture))
{
var records = CsvReader.GetRecords<varMapper>().ToList();
foreach (var item in records)
{
if (item.name != "#N/A" && item.priority != 0)
{
LineItems lineItem = new LineItems();
lineItem.variableName = item.Items;
lineItem.variableUnit = item.Unit;
lineItem.variableGrowthCheck = item.growth;
lineItem.variableAVGCheck = item.avg;
lineItem.variableSVCheck = item.svData;
lineItem.longName = item.name;
lineItem.priority = item.priority;
}
}
}
}
}
public class LineItems
{
public string variableName;
public string variableUnit;
public bool variableGrowthCheck;
public bool variableAVGCheck;
public bool variableSVCheck;
public string longName;
public int priority;
}
public class varMapper
{
public string Items { get; set; }
public string Unit { get; set; }
public bool growth { get; set; }
public bool avg { get; set; }
public bool svData { get; set; }
public string name { get; set; }
public int priority { get; set; }
}
You should write your method to return a list.
public List<LineItems> GetMapper()
{
using (var StreamReader = new StreamReader(#"D:\Data\Projects\dictUnitMapper.csv"))
{
using (var CsvReader = new CsvHelper.CsvReader(StreamReader, CultureInfo.InvariantCulture))
{
return
CsvReader
.GetRecords<varMapper>()
.Where(item => item.name != "#N/A")
.Where(item => item.priority != 0)
.Select(item => new LineItems()
{
variableName = item.Items,
variableUnit = item.Unit,
variableGrowthCheck = item.growth,
variableAVGCheck = item.avg,
variableSVCheck = item.svData,
longName = item.name,
priority = item.priority,
})
.ToList();
}
}
}
Here's an alternative syntax for building the return value:
return
(
from item in CsvReader.GetRecords<varMapper>()
where item.name != "#N/A"
where item.priority != 0
select new LineItems()
{
variableName = item.Items,
variableUnit = item.Unit,
variableGrowthCheck = item.growth,
variableAVGCheck = item.avg,
variableSVCheck = item.svData,
longName = item.name,
priority = item.priority,
}
).ToList();

Hide empty columns in DataGridView

I'm working in c# with Windows form.
I've an item DataGridView named objGridView, used like this :
public partial class dlgDetailsObj : Form
{
public dlgDetailsObj(myInterface item)
{
InitializeComponent();
objGridView.DataSource = new BindingList<dlgItem>();
var t = new Task(() =>
{
List<dlgItem> listElements = new List<dlgItem>();
if (item is List<Person>)
{
List<Person> list = (List<Person>)item;
foreach (Person person in list)
{
listElements.Add(new dlgItem()
{
Name = person.Name,
Forname = person.Forname
});
}
}
else if (item is List<Compagny>)
{
List<Compagny> list = (List<Compagny>)item;
foreach (Compagny compagny in list)
{
listElements.Add(new dlgItem()
{
Compagny = compagny.Name
});
}
}
else
{
return;
}
foreach (dlgItem item in listElements)
{
objGridView.Invoke((MethodInvoker)delegate
{
int sel = objGridView.GetSelectedRowIndex();
((BindingList<dlgItem>)objGridView.DataSource).Add(item);
objGridView.SetSelectedRowIndex(sel);
});
}
});
t.Start();
}
}
internal class dlgItem
{
public string Name { get; set; }
public String Forname { get; set; }
public String Compagny { get; set; }
}
The class dlgDetailsObj is used to display a list of Persons/Companies and probably more object later.
My DataGridView has a DataSource filled of dlgItem. Actually all three fields are displayed, even if I only only one.
How can I define my code to display columns only if binded fields are not null ?
If you want to hide all empty columns you could iterate through the DataSource collection to determine whether the corresponding property has been set for any dlgItem object:
public dlgDetailsObj(myInterface item)
{
InitializeComponent();
objGridView.DataSource = new BindingList<dlgItem>();
var t = new Task(() =>
{
...
});
t.Start();
t.ContinueWith(task =>
{
bool displayNameColumn = false;
bool displayFornameColumn = false;
bool displayCompanyColumn = false;
foreach (dlgItem item in (BindingList<dlgItem>)objGridView.DataSource)
{
if (!string.IsNullOrEmpty(item.Name))
displayNameColumn = true;
if (!string.IsNullOrEmpty(item.Forname))
displayFornameColumn = true;
if (!string.IsNullOrEmpty(item.Compagny))
displayCompanyColumn = true;
}
objGridView.Columns[0].Visible = displayNameColumn;
objGridView.Columns[1].Visible = displayFornameColumn;
objGridView.Columns[2].Visible = displayCompanyColumn;
}, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}

How to apply lazy loading to bing ListView in windows store app?

I am working on Sales App of Windows Store app. I want to apply lazy loading for my product module.
When Product page open it get product from backend and show in ListBox control.
It takes time everytime to load. I think main reason is when I check for the image exists on given url.
Here is my code and class:
private async Task getAllProductDetails()
{
var resultproductlist = await client.PostAsync(session.Values["URL"] + "/magemobpos/product/getProductList", contents);
if (resultproductlist.IsSuccessStatusCode)
{
string trys = resultproductlist.Content.ReadAsStringAsync().Result;
List<Productlistdata> objProducts = JsonConvert.DeserializeObject<ProductlistResponse>(trys).productlistdata;
Productlistdata Product;
//all product are in objProducts
foreach (var item in objProducts)
{
bool imageexist = false;
//check if image exist on given url or not
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(item.image.ToString()));
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
int imagelength = Convert.ToInt32(response.ContentLength);
if (imagelength > 0)
imageexist = true;
else
imageexist = false;
}
}
catch (Exception)
{
imageexist = false;
}
//if image not exist, it get default image
if (item.image.ToString().ToLower().Equals("n/a") || imageexist == false)
{
item.image = "Images/NoDataImages/ico-no-orders.png";
}
Product = new Productlistdata()
{
image = item.image,
name = item.name,
price = item.price,
sku = item.sku,
type = item.type[0],
id = item.id
};
//add all product in lstProduct. lstProduct is ListBox Control
lstProduct.Items.Add(Product);
}
}
}
Class:
public class Productlistdata
{
public string id { get; set; }
public string sku { get; set; }
public string name { get; set; }
public string status { get; set; }
public string qty { get; set; }
public string price { get; set; }
public string image { get; set; }
public string type { get; set; }
public string full_productname { get; set; }
}
Can anybody suggest me how to apply lazy loading? I don't know exactly but I think it can apply to bind image once the list is loaded.
I know that you dint ask for it but I ll strongly suggest you to look into Bindings I believe it will help you a lot thinking what you are trying to build. So I ll start by changing some of your code using bindings and then go to the real solution.
Here is what you can try and do:
First remove this code:
bool imageexist = false;
//check if image exist on given url or not
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(item.image.ToString()));
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
int imagelength = Convert.ToInt32(response.ContentLength);
if (imagelength > 0)
imageexist = true;
else
imageexist = false;
}
}
catch (Exception)
{
imageexist = false;
}
Second Step is to get rid of this code
//add all product in lstProduct. lstProduct is ListBox Control
lstProduct.Items.Add(Product);
Now add on top of you page.xaml.cs an ObservableCollection
private ObservableCollection<Productlistdata> productlist = new ObservableCollection<Productlistdata>();
public ObservableCollection<Productlistdata> Productlist
{
get { return productlist ?? (productlist= new ObservableCollection<Productlistdata>()); }
set { productlist= value; }
}
Now you either bind that list in the list box like this
<ListBox ItemsSource="{Binding Productlist}"/>
or In the Contractor of your page do
lstProduct.ItemsSource = Productlist;
That way Productlist is binded to your ListBox and when you add or remove items will it will be updated automatically.
Now you can skip all the above but I suggest you to look into Bindings it powerfull and will solve many of your problems when you get the idea of they work.
Now we will add the first code we removed in your ProductListdata
public class Productlistdata
{
public string id { get; set; }
public string sku { get; set; }
public string name { get; set; }
public string status { get; set; }
public string qty { get; set; }
public string price { get; set; }
public string image { get; set; }
public string type { get; set; }
public string full_productname { get; set; }
public async void CheckImage()
{
bool imageexist = false;
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(image));
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
int imagelength = Convert.ToInt32(response.ContentLength);
if (imagelength > 0)
imageexist = true;
else
imageexist = false;
}
}
catch (Exception)
{
imageexist = false;
}
if (!imageexist)
{
image = "Images/NoDataImages/ico-no-orders.png";
}
}
}
And populate your List
private async Task getAllProductDetails()
{
var resultproductlist = await client.PostAsync(session.Values["URL"] + "/magemobpos/product/getProductList", contents);
if (resultproductlist.IsSuccessStatusCode)
{
string trys = resultproductlist.Content.ReadAsStringAsync().Result;
List<Productlistdata> objProducts = JsonConvert.DeserializeObject<ProductlistResponse>(trys).productlistdata;
//all product are in objProducts
foreach (var item in objProducts)
{
Productlistdata Product = new Productlistdata()
{
image = item.image,
name = item.name,
price = item.price,
sku = item.sku,
type = item.type[0],
id = item.id
};
Product.CheckImage();
Productlist.Add(Product);
}
}
}
Product.CheckImage(); will not be awaited. So the Items in the list will load really fast because nothing is awaited in the foreach loop. Product.CheckImage(); will run on another thread at later time.
Finally because image might change after the data is loaded on the ListBoxa(when image wasnt fount) you will have to Notify the UI that a property has changed. To do that you will have to use INotifyPropertyChanged. You can take a look in an other answer of mine how to do that here
I would suggest changing your queries,
firstly instead of getAllProductDetails do getAllProductID
so where you have
var resultproductlist = await client.PostAsync(session.Values["URL"] + "/magemobpos/product/getProductList", contents);
if (resultproductlist.IsSuccessStatusCode)
{
string trys = resultproductlist.Content.ReadAsStringAsync().Result;
List<Productlistdata> objProducts = JsonConvert.DeserializeObject<ProductlistResponse>(trys).productlistdata;
Productlistdata Product;
you would do
var resultproductlist = await client.PostAsync(session.Values["URL"] + "/magemobpos/product/getProductID", contents);
if (resultproductlist.IsSuccessStatusCode)
{
string trys = resultproductlist.Content.ReadAsStringAsync().Result;
List<int> objProducts = JsonConvert.DeserializeObject<ProductlistResponse>(trys).productlistdata;
LazyProductlistdata Product;
secondly create a wrapper
public LazyProductlistdata
{
public string id { get; set; }
private Lazy<Productlistdata> data = new Lazy<Productlistdata>(()=>Productlistdata.CreateFromID(id));
public Productlistdata Data
{
get{return data.Value;}
}
}
expand this so the wrapper contains information required for sorting
finally alter the constructor or create a factory for Productlistdata so that it obtains the individual record from the source
public class Productlistdata
{
public static Productlistdata CreateFromID(int id)
{
//Return single Productlistdata from webservice
}
}
NOTE: lazy loading will increase the overall load time, the advantange is that instead of it being 1 huge block of time its several smaller ones
I would suggest using Converter to supply placeholder see here.
You can also decorate Image.Source binding with IsAsync = True - so that main thread would not be blocked
You can use ImageFailed event to assign image placeholder
foreach (var item in objProducts)
{
var bitmap = new BitmapImage();
bitmap.ImageFailed += (s, e) => bitmap.UriSource = defaultImageUri;
bitmap.UriSource = new Uri(item.image);
item.Add(bitmap);
//set decodepixelwidth and dicodepixelheight correctly to avoid outofmemory exception
}

WPF DataBinding ListBox in MVVM Pattern

I am databind Listbox in MVVM pattern,I am using Entity Framework for getting data,this is how I am doing
XAML:
<ListBox Margin="0,26,860,-146" x:Name="lstuser" ItemsSource="{Binding ListBoxDS}"/>
C# code:
private ObservableCollection<Users> _lstusers;
public ObservableCollection<Users> ListBoxDS
{
get
{
if (_lstusers == null)
{
_lstusers = new ObservableCollection<Users>();
}
return _lstusers;
}
set
{
_lstusers = value;
NotifyOfPropertyChange("ListBoxDS");
}
}
public class Users
{
public int UserID { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
}
DataContext:
public static IList<Users> GetAllUsers
{
try
{
using (var context = new ApplicationContext())
{
return context.UsersInfo.ToList();
}
}
finally
{
}
}
and in my ViewModel
var allusersList=GetAllUsers();
var users = allusersList.Where(a => a.FirstName =="some value").ToList();
foreach (var item in users)
{
_lstusers.Add(new Users { UserID = item.Id, UserName = item.Username,FirstName=item.firstname });
}
When I am ruuning my project,its not showing any item in Listbox, I am following this link
I have debugged it, data is appearing in ListDS.
in your code i cant see that you add the item to your list. it should be
var users = allusersList.Where(a => a.FirstName =="some value").ToList();
foreach (var item in users)
{
ListBoxDS.Add(new Users { UserID = item.Id, UserName = item.Username,FirstName=item.firstname });
}
EDIT: then your code should work if you set the right DataContext. you can check this with Snoop at runtime.

How to not get repeated names appeared in the Combo Box c#

I encountered a problem where I can't seem to make the names in the Combo Box appear once instead of multiple one. Is there anything in my codes that causes this problem? Any help will be greatly appreciated.
Below is the code to link the names to the combo Box.
private void Create_EmpDetails_Load(object sender, EventArgs e)
{
using (satsEntities Setupctx = new satsEntities())
{
var viewEmpName = (from viewEN in Setupctx.employees
join ufi u in Setupctx.ufis on viewEN.UFISID equals u.UFISID
select new { u.EmployeeName , u.UFISID}).Distinct().ToList();
cbName.DataSource = viewEmpName;
cbName.DisplayMember = "EmployeeName";
cbName.ValueMember = "EmployeeName";
//cbName.ValueMember = "UFISID";
}
}
Each of those rows has a different UFISID, so Distinct() is not removing them.
It sounds like you just want to show employees:
cbName.DataSource = Setupctx.Employees;
I edited to my codes to this and I managed to show only 1 name for instead of multiple records.
private void Create_EmpDetails_Load(object sender, EventArgs e)
{
using (satsEntities Setupctx = new satsEntities())
{
var viewEmpName = (from viewEN in Setupctx.employees
join ufi u in Setupctx.ufis on viewEN.UFISID equals u.UFISID
select new { u.EmployeeName }).Distinct().ToList();
cbName.DataSource = viewEmpName;
cbName.DisplayMember = "EmployeeName";
cbName.ValueMember = "EmployeeName";
//cbName.ValueMember = "UFISID";
}
}
Probably, it would be enough for you to replace
select new { u.EmployeeName , u.UFISID}
with
select new { u.EmployeeName }
in combobaxes we display the string as DisplayMember for users and id of members(maybe important for us) as ValueMember for us. more time we work with ids . my example :
class Country
{
public string Name { get; set; }
public int ID { get; set; }
public Country( int i,string s) { Name = s; ID = i; }
}
class ComboItem
{
public string DisplayMember { get; set; }
public int ValueMember { get; set; }
}
class ComboItemEqualityComparer : IEqualityComparer<ComboItem>
{
public bool Equals(ComboItem item1, ComboItem item2)
{
if (item1.ValueMember == item2.ValueMember && item1.DisplayMember == item2.DisplayMember)
{
return true;
}
return false;
}
public int GetHashCode(ComboItem item)
{
string str = item.DisplayMember + item.ValueMember;
return str.GetHashCode();
}
}
test :
List<Country> countries = new List<Country> {
new Country(1,"UK"),
new Country(2,"Turkey"),
new Country(8,"Turkey"),
new Country(5,"Turkey"),
new Country(2,"Turkey"),
new Country(3,"USA") ,
new Country(3,"USA")}; //.Distinct(new CountryEqualityComparer()).ToList();
var Data = (from i in countries
select new ComboItem { ValueMember = i.ID, DisplayMember = i.Name }).Distinct(new ComboItemEqualityComparer()).ToList();
cbName.DataSource = Data;
cbName.DisplayMember = "DisplayMember";
cbName.ValueMember = "ValueMember";
sometimes we have data that have displayname the same but the id of them arent. we can change the ComboItemEqualityComparer equals method to :
public bool Equals(ComboItem item1, ComboItem item2)
{
if (item1.ValueMember == item2.ValueMember )
{
return true;
}
return false;
}
enjoy.
for this question we can :
....
select new ComboItem { ValueMember = u.UFISID, DisplayMember = u.EmployeeName }).Distinct(new yourIEqualityComparer()).ToList();

Categories

Resources