How to bind List Data to combobox - c#-4.0

I mae a WCF service that contain this method :
public List<LocationDB> GetLocation()
{
List<LocationDB> locations = null;
using (SqlConnection connection = new SqlConnection(conn))
{
using (SqlCommand command = new SqlCommand())
{
command.Connection = connection;
command.CommandText = string.Format("Select L_ID ,L_Name from Location");
connection.Open();
//code to fill the locations list..
my problem is when i want to bind the result from this method in my code i do the following.
void MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
client.GetLocationCompleted += new EventHandler<GetLocationCompletedEventArgs>(client_GetLocationCompleted);
client.GetLocationAsync();
}
}
and :
void client_GetLocationCompleted(object sender, GetLocationCompletedEventArgs e)
{
LocationCombo.ItemsSource = e.Result;
LocationCombo.SelectedValuePath =
LocationCombo.DisplayMemberPath =
}
and finally my LocationDB Class that is located in the App_code folder in the asp web site:
[DataContract]
public class LocationDB
{
[DataMember]
public int Lid { get; set; }
[DataMember]
public int SmId { get; set; }
[DataMember]
public string Lname { get; set; }
how can i bind the SelectedValePath and the DisplayMemberPath in code behind not in XAML.
Thanks

From what I can tell you already have everything you need although some of it needs to be in a different order.
void client_GetLocationCompleted(object sender, GetLocationCompletedEventArgs e)
{
LocationCombo.SelectedValuePath = "Lid";
LocationCombo.DisplayMemberPath = "Lname";
LocationCombo.ItemsSource = e.Result;
}

You should be able to set each of them to a string which represents the property (on the bject you're binding to) to use as the SelectedValuePath and DisplayMemberPath respectively:
LocationCombo.SelectedValuePath = "Lid";
LocationCombo.DisplayMemberPath ="Lname";
LocationCombo.ItemsSource = e.Result.ToList();

Related

How can I load data for multiple TabPages concurrently in a WinForms application

I have a Windows Forms application with a TabControl containing multiple TabPages. Each TabPage contains many controls whose data is read from a database via a web api. I want to be able to display at least one TabPage, with it's data, while the remaining TabPages are loading. I know I can't load a control in a thread, so I need a way to do the data retrieval in the background, concurrently, for each of the TabPages and then use the data retrieved to fill in the controls on each TabPage. So my question is: what would be the ideal method for doing this? I want to prioritize performance. I also want to have some visual indication on each TabPage header that the page is still loading. Thoughts? Ideas? Direct answers?
You can load data in parallel threads and just after loading data completed, then update UI (legally) by calling Invoke method to prevent cross-thread exception. You can also load data using tasks in parallel, and update data when each task is completed.
In the following examples, the data is loading in parallel threads and as soon as each thread/task is done, the UI will be updated.
Example 1 - Using Task to load data into UI in parallel
private NorthwindClient client = new NorthwindClient();
private void Form1_Load(object sender, EventArgs e)
{
LoadCategories();
LoadProducts();
}
private void LoadProducts()
{
productsTabPage.Text = "Loading ...";
var products = client.GetProductsAsync().GetAwaiter();
products.OnCompleted(() =>
{
productsDataGridView.DataSource = products.GetResult();
productsTabPage.Text = "Products";
});
}
private void LoadCategories()
{
categoriesTabPage.Text = "Loading ...";
var categories = client.GetCategoriesAsync().GetAwaiter();
categories.OnCompleted(() =>
{
categoriesDataGridView.DataSource = categories.GetResult();
categoriesTabPage.Text = "Categories";
});
}
Example 2 - Using Thread to load data into UI in parallel
private NorthwindClient client = new NorthwindClient();
private void Form1_Load(object sender, EventArgs e)
{
LoadCategories();
LoadProducts();
}
private void LoadProducts()
{
productsTabPage.Text = "Loading ...";
new Thread(() =>
{
var products = client.GetProducts();
Invoke(new Action(() =>
{
productsDataGridView.DataSource = products;
productsTabPage.Text = "Products";
}));
}).Start();
}
private void LoadCategories()
{
categoriesTabPage.Text = "Loading ...";
new Thread(() =>
{
var categories = client.GetCategories();
Invoke(new Action(() =>
{
categoriesDataGridView.DataSource = categories;
categoriesTabPage.Text = "Categories";
}));
}).Start();
}
NorthwindClient - Common code for both examples
Both above examples rely on the following code to load data:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
public class NorthwindClient
{
static HttpClient client;
static NorthwindClient()
{
client = new HttpClient();
client.BaseAddress = new Uri("https://northwind.vercel.app/api/");
}
public async Task<IEnumerable<Category>> GetCategoriesAsync()
{
var response = await client.GetStringAsync("categories");
return JsonConvert.DeserializeObject<IEnumerable<Category>>(response);
}
public async Task<IEnumerable<Product>> GetProductsAsync()
{
var response = await client.GetStringAsync("products");
return JsonConvert.DeserializeObject<IEnumerable<Product>>(response);
}
public IEnumerable<Category> GetCategories()
{
var response = client.GetStringAsync("categories").Result;
return JsonConvert.DeserializeObject<IEnumerable<Category>>(response);
}
public IEnumerable<Product> GetProducts()
{
var response = client.GetStringAsync("products").Result;
return JsonConvert.DeserializeObject<IEnumerable<Product>>(response);
}
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class Product
{
public int Id { get; set; }
public int SupplierId { get; set; }
public int categoryId { get; set; }
public string QuantityPerUnit { get; set; }
public decimal UnitPrice { get; set; }
public int UnitsInStock { get; set; }
public int UnitsOnOrder { get; set; }
public int ReorderLevel { get; set; }
public bool Discontinued { get; set; }
public string Name { get; set; }
}

Xml Parsing in C#

http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.atom on this site, I wrote the following code to retrieve the data.
protected void Button1_Click(object sender, EventArgs e)
{
string adresal = "http://" + txtAd.Text;
WebResponse GelenCevap;
WebRequest adresistegi = HttpWebRequest.Create(adresal);
GelenCevap = adresistegi.GetResponse();
StreamReader CevapOku = new StreamReader(GelenCevap.GetResponseStream());
string KaynakKodlar = CevapOku.ReadToEnd();
XmlDocument xmlDoc = new XmlDocument(); // Create an XML document object
xmlDoc.Load("http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.atom"); // Load the XML document from the specified file
XmlNodeList depremler = xmlDoc.GetElementsByTagName("entry");
foreach (XmlNode node in depremler)
{
var a = node.ChildNodes;
foreach (XmlElement x in a)
{
ListBox1.Items.Add(x.InnerText);
}
}
}
In this way I get all the data in the ListBox.But I need to assign them to variable data line by line.How can I do? I would appreciate if you can help.
Also i need id,title, updated, georss:point,georss:elev variables.
First add an Enrty and Category class:
public class Entry
{
public string Id { get; set; }
public string Title { get; set; }
public string Updated { get; set; }
public string Summary { get; set; }
public string GPoint { get; set; }
public string GElev { get; set; }
public List<string> Categories { get; set; }
}
public class Category
{
public string Label { get; set; }
public string Term { get; set; }
}
Then use LINQ to XML
XDocument xDoc = XDocument.Load("path");
List<Entry> entries = (from x in xDoc.Descendants("entry")
select new Entry()
{
Id = (string) x.Element("id"),
Title = (string)x.Element("title"),
Updated = (string)x.Element("updated"),
Summary = (string)x.Element("summary"),
GPoint = (string)x.Element("georss:point"),
GElev = (string)x.Element("georss:elev"),
Categories = (from c in x.Elements("category")
select new Category
{
Label = (string)c.Attribute("label"),
Term = (string)c.Attribute("term")
}).ToList();
}).ToList();

Assign value to workflow variable

I have one question about Windows Workflow Foundation 4. I have an activity named PositionArrayActivity. This activity has a Sequence activity inside it. I need that in Execute method (during the workflow execution) oneFund variable mapping his value to PORTFOLIO_NAME that is created in Create method.... What have I to do to mapping oneFund value to PORTFOLIO_NAME at runtime?
Thanks
public sealed class PositionArrayActivity : NativeActivity, IActivityTemplateFactory
{
[Browsable(false)]
public Dictionary<string, List<Entity>> dictionary = new Dictionary<string, List<Entity>>();
public ActivityAction<Entity[]> Body { get; set; }
public Entity[] PositionList { get; set; }
public SqlDataReader rdr;
public SqlDataReader sdr;
public Entity[] positionArray;
public List<String> fundList;
public String oneFund { get; set; }
public String date { get; set; }
public List<Entity> listToArrayPositions;
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
metadata.AddDelegate(Body);
}
protected override void Execute(NativeActivityContext context)
{
// A lot of code....
}
public Activity Create(DependencyObject target)
{
Variable<string> var = new Variable<string>
{
Name = "PORTFOLIO_NAME"
};
var fef = new PositionArrayActivity();
var aa = new ActivityAction<Entity[]>();
var da = new DelegateInArgument<Entity[]>();
da.Name = "positions";
fef.Body = aa;
aa.Argument = da;
aa.Handler = new Sequence
{
Variables = { var }
};
return fef;
}
}
You need to have an ActivityContext to set a variable value so first move the declaration of the var (did that name actually compile?) to a higher scope.
Then in Execute
var.Set(activityContext, oneFund);
One thing though, the oneFund property will only be set once at application startup so you may have some surprising results. If you wanted that to be for each instance, you need an inargument.

Automapper map custom collections

Hello. I have a list that looks like this one:
public class PagedList<T> : List<T>
{
public PagedList(IEnumerable<T> collection) : base(collection)
{ }
public int TotalItems { get; set; }
public int CurrentPage { get; set; }
public int PageSize { get; set; }
//some other properties
}
and used in repository for paging
public PagedList<TEntity> GetPaged(int page)
{
var pagedEntities = some_query;
return pagedEntities.AsPagedList(totalResults, page, pageSize);
}
The same PagedList is also used in asp mvc view models for paging.
Is it possible to map this collections using Automapper with all the properties TotalItems/CurrentPage/... ?
PagedList<DbItem> dbItems = _repository.GetPages(page);
var viewItems = new PagedList<SomeItemView>();
Mapper.Map(dbItems , viewItems);
Tahnk You !
This worked for me. Are you looking for something more generic?
public class DbItem
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ViewItem
{
public int Id { get; set; }
public string Name { get; set; }
}
public class PagedList<T>: List<T>
{
public int TotalItems { get; set; }
public int CurrentPage { get; set; }
public int PageSize { get; set; }
}
class Program
{
static void Main(string[] args)
{
MapItems();
}
public static void MapItems()
{
Mapper.CreateMap<DbItem, ViewItem>();
Mapper.CreateMap<PagedList<DbItem>, PagedList<ViewItem>>()
.AfterMap((s, d) => Mapper.Map<List<DbItem>, List<ViewItem>>(s, d));
var dbList = new PagedList<DbItem>
{
new DbItem {Id = 1, Name = "a"},
new DbItem {Id = 2, Name = "b"}
};
dbList.TotalItems = 2;
dbList.CurrentPage = 1;
dbList.PageSize = 10;
var viewList = Mapper.Map<PagedList<DbItem>, PagedList<ViewItem>>(dbList);
Console.WriteLine(viewList.TotalItems);
Console.WriteLine(viewList.CurrentPage);
Console.WriteLine(viewList.PageSize);
Console.WriteLine(viewList[0].Id + " " + viewList[0].Name);
Console.WriteLine(viewList[1].Id + " " + viewList[1].Name);
Console.ReadLine();
}
}
What you need is a custom type converter
public class PagedListConverter<TIn, TOut> : ITypeConverter<IPagedList<TIn>, IPagedList<TOut>>
{
public IPagedList<TOut> Convert(AutoMapper.ResolutionContext context)
{
var source = (IPagedList<TIn>)context.SourceValue;
var mapped = Mapper.Map<IList<TOut>>(source);
return new StaticPagedList<TOut>(mapped, source.GetMetaData());
}
}
Usage:
Mapper.CreateMap<IPagedList<Company>, IPagedList<CompanyViewModel>>().ConvertUsing<PagedListConverter<Company, CompanyViewModel>>();
For those who have faced the similar problem recently, and as an update to NoPyGod's answer, you can achieve the general mapping using ITypeConverter. According to the official documentation:
AutoMapper also supports open generic type converters with any number of generic arguments:
var configuration = new MapperConfiguration(cfg =>
cfg.CreateMap(typeof(Source<>), typeof(Destination<>)).ConvertUsing(typeof(Converter<,>)));
The closed type from Source will be the first generic argument, and the closed type of Destination will be the second argument to close Converter<,>.
So the custom type converter would be:
private class Converter<TSource, TDestination>
: ITypeConverter<PagedList<TSource>, PagedList<TDestination>>
{
public PagedList<TDestination> Convert(
PagedList<TSource> source,
PagedList<TDestination> destination,
ResolutionContext context) =>
new PagedList<TDestination>(
context.Mapper.Map<List<TSource>, List<TDestination>>(source));
/* Additional settings comes here. */
}
And then register it:
this.CreateMap(typeof(PagedList<>), typeof(PagedList<>)).ConvertUsing(typeof(Converter<,>));

Deserialization of XDocument doesn't work

I have this code:
[Serializable]
[XmlRoot("ISO_CCY_CODES")]
public class IsoCurrencyCodes
{
public IsoCurrencyCodes()
{
IsoCodes = new List<IsoCurrencyCode>();
}
public IsoCurrencyCodes(List<IsoCurrencyCode> isoCodes)
{
IsoCodes = isoCodes;
}
[XmlArrayItem("ISO_CURRENCY")]
public List<IsoCurrencyCode> IsoCodes { get; set; }
public static IEnumerable<IsoCurrencyCode> Get()
{
var doc = XDocument.Parse(XmlStringIsoCodes.XmlSource.Replace("\r\n", ""));
var res = doc.Deserialize<IsoCurrencyCodes>();
return res.IsoCodes;
}
}
[Serializable]
[XmlRoot("ISO_CURRENCY")]
public class IsoCurrencyCode
{
public IsoCurrencyCode()
{
}
[XmlElement(ElementName = "ENTITY")]
public string Entity { get; set; }
[XmlElement(ElementName = "CURRENCY")]
public string Currency { get; set; }
[XmlElement(ElementName = "ALPHABETIC_CODE")]
public string Alpha_Code3 { get; set; }
[XmlElement(ElementName = "NUMERIC_CODE")]
public int NumCode { get; set; }
[XmlElement(ElementName = "MINOR_UNIT")]
public string MinorUnit { get; set; }
}
And this code, for deserialization:
public static XDocument Serialize<T>(this T source)
{
var ser = new XmlSerializer(source.GetType());
var sb = new StringBuilder();
using (var writer = new StringWriter(sb))
{
ser.Serialize(writer, source);
}
return XDocument.Parse(sb.ToString());
}
public static T Deserialize<T>(this XDocument xmlDocument)
{
var xmlSerializer = new XmlSerializer(typeof (T));
using (var reader = xmlDocument.CreateReader())
return (T) xmlSerializer.Deserialize(reader);
}
This is the XML source
But deserialization doesn't work. Please help.
Thanks!
I believe you only want to use XMLArray if you have a collection element for all of the items to sit underneath. For example here it could be ISO_CURRENCIES. I'm assuming you can't change the source in this case, so just use this instead:
[XmlElement("ISO_CURRENCY")]
public List<IsoCurrencyCode> IsoCodes { get; set; }
You should find that works.
Additionally, if you find you have further problems in getting the deserialization classes right, you can have them autogenerated for you from the XML and then you can take a look at the code that is created:
xsd source.xml
xsd source.xsd /c
This will create source.cs which you can then use in your project or adapt for your own uses.
As a further note, you'll find you can't use int for Minor_Unit as it's nullable (look at ANTARCTICA). You can't deserialize straight to an int?, so you'll either have to make it a string or go via another property, look at this question for more information.

Resources