Currently, in course, I am trying to check the LandCode from the class Landen to get the cities from the selectedItem land, but I am parsing something wrong.
public partial class Landen
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Landen()
{
this.Steden = new HashSet<Steden>();
this.Talen = new HashSet<Talen>();
}
public string LandCode { get; set; }
public string Naam { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Steden> Steden { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Talen> Talen { get; set; }
}
public MainWindow()
{
InitializeComponent();
var context = new LandenStedenTalenEntities();
landenListBox.ItemsSource = (from Landen in context.Landen select Landen.Naam).ToList();
}
private void landenListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
using (var entities = new LandenStedenTalenEntities())
{
List<string> steden = new List<string>();
var landcode = ((Landen)landenListBox.SelectedItem).LandCode.ToString();
var gekozenland = entities.Landen.Find(landcode);
foreach(var stad in gekozenland.Steden)
{
steden.Add(stad.Naam);
}
stedenInLandenListBox.ItemsSource = steden.ToList();
}
}
Exception:
Unable to cast object of type 'System.String' to type 'TestEFDieter.Landen'.
I want to add them to a list and show them in a second Listbox.
Can anyone help me out? Thank you.
I would suggest you modify the code inside of the constructor so that the landenListBox will contain actual Landen object and displays only the Naam as it's item.
Change the code in the constructor to this:
public MainWindow()
{
InitializeComponent();
var context = new LandenStedenTalenEntities();
landenListBox.ItemsSource = context.Landen.ToList();
landenListBox.DisplayMemberPath = "Naam";
}
Adding DisplayMemberPath will inform ListBox to display that particular property as an item instead of calling ToString() method on that object.
Now in your later code you do not have to change much, just remove ToList() and since you're using EntityFramework you should insert the whole model in it's Find() method but it's useless since you already have that object loaded. You can just retrieve stad from it directly and display it in the same way Landen is displayed:
private void landenListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var landen = landenListBox.SelectedItem as Landen; // safe cast just in case
if (landen != null && landen.Steden != null ) // null checks
{
stedenInLandenListBox.ItemsSource = landen.Steden.ToList(); // in case it's proxy object
stadenInLandenListBox.DisplayMemberPath = "Naam";
}
}
I suppose you want to get that instance of Landen which corresponds the selected item in your list. As the elements in the listbox are just strings that represent the Naam-property of every Landen, you could simply iterate your list of Landen and get that one with the desired Naam:
var selectedLanden = landenList.FirstOrDefault(x => x.Naam == landenListBox.SelectedItem);
if(selectedLanden != null)
{
var landCode = selectedLanden.LandCode;
// ...
}
However as selectedLanden already is an instance of Landen, you won´t need to find it again by its LandCode. Thus your code boils donw to this:
List<string> steden = new List<string>();
var selectedLanden = landenList.FirstOrDefault(x => x.Naam == landenListBox.SelectedItem);
if(selectedLanden != null)
{
foreach(var stad in selectedLanden.Steden)
{
steden.Add(stad.Naam);
}
}
stedenInLandenListBox.ItemsSource = steden.ToList();
or a bit shorter:
stedenInLandenListBox.ItemsSource = selectedLanden.SelectMany(x => x.Steden.Select(y => y.Naam)).ToList();
For this to work you of course have to store a reference to the list of Landen somewehere in your class:
class MainWindow
{
List<Landen> landenList;
public MainWindow()
{
InitializeComponent();
this.landenList = new LandenStedenTalenEntities();
landenListBox.ItemsSource = (from Landen in this.landenList select Landen.Naam).ToList();
}
}
Related
So I have a parent class called SalesRep and a child class called SeniorSalesRep. I have got it so it displays both classes polymorphically to a listbox. The issue I'm having is that I have a combo box that gives the user the choice of displaying a report of the objects in the SalesRep class which should also display the SeniorSalesRep objects and if it's selected just SeniorSalesRep it only shows SeniorSales Rep objects. However, when I'm implementing this it creates an extra object called object which displays only SalesRepObjects and not SeniorSalesRep objects. How can I get rid of that extra object in my combo box?
public void LoadTypeComboBox()
{
List<string> salesRepTypes = new List<string>();
foreach (SalesRep thisSalesRep in allSalesReps)
{
string s = thisSalesRep.GetType().Name;
string baseType = thisSalesRep.GetType().BaseType.Name;
if (!salesRepTypes.Contains(s))
{
salesRepTypes.Add(s);
}
if (!salesRepTypes.Contains(baseType))
{
salesRepTypes.Add(baseType);
}
}
cboObjectType.DataSource = salesRepTypes;
}
private void cboObjectType_SelectedIndexChanged(object sender, EventArgs e)
{
lstSalesReps.DataSource = null;
lstSalesReps.Items.Clear();
foreach (var i in allSalesReps)
{
if (i.GetType().Name == cboObjectType.SelectedItem.ToString())
{
lstSalesReps.Items.Add(i);
}
else if (i.GetType().BaseType.Name == cboObjectType.SelectedItem.ToString())
{
lstSalesReps.Items.Add(i);
}
}
}
Form Output
The code that shows object in combobox is this:
string baseType = thisSalesRep.GetType().BaseType.Name;
The base type of SalesRep is object. You should either remove object from your collection or never add in the first place.
GetType gives you the runtime type of the object. So I don't think you need .BaseType. Try this:
public void LoadTypeComboBox()
{
List<string> salesRepTypes = new List<string>();
foreach (SalesRep thisSalesRep in allSalesReps)
{
string type = thisSalesRep.GetType().Name;
if (!salesRepTypes.Contains(s))
{
salesRepTypes.Add(s);
}
}
cboObjectType.DataSource = salesRepTypes;
}
Or even better with Linq:
cboObjectType.DataSource = allSalesReps
.Select(r => r.GetType().Name)
.Distinct()
.ToList();
I have this method
Meeting is a class
Attendees is an ICollection in Meeting
Class
public partial class Meeting
{
public Meeting()
{
this.Attendees = new List<Attendees>();
}
public virtual ICollection<Attendees> Attendees{ get; set; }
[...]
Method Controller
private void RemoveRowsDuplicated(Meeting model)
{
if (model.Attendees != null)
{
foreach (var item in model.Attendees.GroupBy(x => x.UserName).Select(y => y.Last()))
{
context.Attendees.Remove(item);
}
}
}
The objective is remove duplicate Attendees with the same username in the table.
But the current method it deletes all records and keeps the duplicate
Where am I going wrong?
Correct version of your method will look like this:
private static void RemoveRowsDuplicated(Meeting model)
{
if (model.Attendees != null)
{
var duplicates = new List<Attendees>();
foreach (var item in model.Attendees.GroupBy(x => x.UserName).Where(x=>x.Count()>1))
{
duplicates.AddRange(item.Skip(1));
}
duplicates.ForEach(x=>context.Attendees.Remove(x));
}
}
You can try writing raw SQL and invoking via EF and return Attendees objects in a list.
var query = "Select * from Attendees group by username";
var attendeesList = dbContext.Database.SqlQuery<Attendees>(query).ToList<Attendees>();
As I can see you grouped elements by name and remove last item. So you remove unique elements.
Like this
private void RemoveRowsDuplicated(Meeting model)
{
if (model.Attendees != null)
{
var temporaryAtendees = new List<Attendees>();
foreach(var item in model.Attendees)
{
if (temporaryAtendees.Contains(item))
{
context.Attendees.Remove(item);
}
else
{
temporaryAtendees.Add(item);
}
}
}
}
I am testing a simple code block to be used in my project.Firsly I want to give example. Here is the class
class Processing
{
public string Region { get; set; }
public Car _car {get;set;}
public double Kilometer { get; set; }
}
class Car
{
public string LicansePlate { get; set; }
public string Driver { get; set; }
public double OdoMeter { get; set; }
}
Now. I have created List of Processing.This list contatin:
String Region
Car _car
double Kilometer
I want to make list flatten using SelectMany() simply. Why I am using this way is SelectMany() will take "var" as referance in future.My Target outpur is like that :
Region LicancePlate Driver Odometer Kilometer
... ... ... ... ...
... ... ... ... ...
This code block is only test.Main Block is like that.
public partial class MainWindow : Window
{
List<Processing> proces;
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
proces= new List<Processing>(){
new Processing {Region="Konya",Kilometer=96,_car= new Car(){LicansePlate="34 ABR 45", Driver="Hasan Doğan", OdoMeter=1322}},
new Processing {Region="Karaman",Kilometer=233,_car=new Car{ LicansePlate="34 JT 9809" ,Driver="Ahmet Turgut",OdoMeter=1231}},
new Processing { Region = "Ankara", Kilometer = 57, _car=new Car {LicansePlate = "34 JK 8547", Driver = "Tuncay Yıldız", OdoMeter = 472 }}
};
var kk = proces.SelectMany(b => b);
dtgrid.ItemsSource = kk.ToList();
}
var kk = kullanımlar.SelectMany(b => b); sentences give error.How to get all rows with sub field using SelectMany().Error is following :
cannot be inferred from the usage. Try specifying the type arguments explicitly.
It looks like you want Select instead of SelectMany:
var kk = proces.Select(p => new {
Region = p.Region,
LicencePlate = p.c.LicencePlate,
Driver = p.c.Driver,
Odometer = p.c.Odometer,
Kilometer = p.Kilometer
});
If you want a "plane" list then you have to iterate properties.
you can do like this for example
write a recursive func that iterates proces[0] properties
proces[0].getType().GetProperties()
could do getting properties...
when iteration gets a propertiy push in a Expando or something like then you there
you have a DYNAMIC FLAT list :)
In turkish, liste ne olursa olsun grid benzeri bir liste için propertiler içerisindeki classları da bir döngüyle alıp expando obje içine bas.. olay biter ;)
kolaylıklar diliyorum... Take it easy...
I have two property in my class: MyCountry & MyCity. I set this class to sourceobject of a property grid. I want load cities i combo when select a country. for example I have 2 Country data:
Country1
Country2
And For Country1, I have (city data)
City11
City12
City13
And For Country2, I have (city data)
city21
City22
City23
When I change select country item in propertygrid, I want load cities of it in city item. this mean, when select Country1, display City11,City12,City13 in City item and when select Country2 Display City21,Cityy22,City23 in City Item.
How can I It ?
my class is :
public class KeywordProperties
{
[TypeConverter(typeof(CountryLocationConvertor))]
public string MyCountry { get; set; }
[TypeConverter(typeof(CityLocationConvertor))]
public string MyCity { get; set; }
}
and I use below class for load countries data for display in combo :
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
HumanRoles Db = new HumanRoles();
List<LocationsFieldSet> Items = new List<LocationsFieldSet>();
Items = Db.LoadLocations(0);
string[] LocationItems = new string[Items.Count];
int count = 0;
foreach (LocationsFieldSet Item in Items)
{
LocationItems[count] = Item.Title;
count++;
}
return new StandardValuesCollection(LocationItems);
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return true;
}
}
The ITypeDescriptorContext interface provides a property called Instance
which lets you access the object to which the type descriptor request is connected.
You can use this property to determine the current value of the MyCountry property
the user selected. Depending on the value you can load the cities for this country.
Furthermore, in the setter of the MyCountry property I check whether or not the
new value is different from the old one and if this is the case I reset the MyCity property
(to not get an invalid combination of country and city).
Here is a small code sample. For the sake of simplicity I only use one type converter
for both properties.
public class KeywordProperties
{
public KeywordProperties()
{
MyCountry = "Country1";
}
private string myCountry;
[TypeConverter(typeof(ObjectNameConverter))]
public string MyCountry
{
get { return myCountry; }
set
{
if (value != myCountry)
MyCity = "";
myCountry = value;
}
}
private string myCity;
[TypeConverter(typeof(ObjectNameConverter))]
public string MyCity
{
get { return myCity; }
set { myCity = value; }
}
}
public class ObjectNameConverter : StringConverter
{
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
KeywordProperties myKeywordProps = context.Instance as KeywordProperties;
if (context.PropertyDescriptor.Name == "MyCountry")
{
List<string> listOfCountries = new List<string>();
listOfCountries.Add("Country1");
listOfCountries.Add("Country2");
return new StandardValuesCollection(listOfCountries);
}
List<string> listOfCities = new List<string>();
if (myKeywordProps.MyCountry == "Country1")
{
listOfCities.Add("City11");
listOfCities.Add("City12");
listOfCities.Add("City13");
}
else
{
listOfCities.Add("City21");
listOfCities.Add("City22");
listOfCities.Add("City23");
}
return new StandardValuesCollection(listOfCities);
}
}
In the example above there is one side effect I do not like.
Setting the MyCountry property leads to settting also the MyCity property.
To workaround this side effect you could also use the PropertyValueChanged event
of the PropertyGrid to handle invalid country/city selections.
private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
{
if (e.ChangedItem.Label == "MyCountry")
{
if(e.ChangedItem.Value != e.OldValue)
m.MyCity = "";
}
}
If you use this event, just repalce the code in the setter of the MyCountry property with:
myCountry = value;
I am facing a problem. I have set of some enum in my app. Like
public enum EnmSection
{
Section1,
Section2,
Section3
}
public enum Section1
{
TestA,
TestB
}
public enum Section2
{
Test1,
Test2
}
EnmSection is main enum which contains the other enum(as string) which are declared below it. Now i have to fill the values of EnmSection in a drop-down.I have done it.
Like this...
drpSectionType.DataSource = Enum.GetNames(typeof(EnmSection));
drpSectionType.DataBind();
Now my drop-down has values: Section1,Section2,Section3
Problem is:
I have another drop-down drpSubSection. Now i want to fill this drop-down whatever i have selected in the drpSectionType.
for ex If I selected Section1 in drpSectionType then drpSubsection should contain the value
TestA,TestB. Like this:
protected void drpSectionType_SelectedIndexChanged(object sender, EventArgs e)
{
string strType = drpSectionType.SelectedValue;
drpSubsection.DataSource = Enum.GetNames(typeof());
drpSubsection.DataBind();
}
Here typeof() is expecting the enum.But i am getting selected value as string. How can i achieve this functionality.
Thanks
What if you reference an assembly that contains another enum with a value named Section1?
You'll just have to try all the enums you care about, one at a time, and see which one works. You'll probably want to use Enum.TryParse.
Something like this might work, but you have to do some exception handling:
protected void drpSectionType_SelectedIndexChanged(object sender, EventArgs e)
{
string strType = drpSectionType.SelectedValue;
EnmSection section = (EnmSection)Enum.Parse(typeof(EnmSection), strType);
drpSubsection.DataSource = Enum.GetNames(typeof(section));
drpSubsection.DataBind();
}
This might be a bit over the top but it would work if you bind bind Arrays of IEnumItem to your drop down and set it up to show their display text.
public interface IEnumBase
{
IEnumItem[] Items { get; }
}
public interface IEnumItem : IEnumBase
{
string DisplayText { get; }
}
public class EnumItem : IEnumItem
{
public string DisplayText { get; set; }
public IEnumItem[] Items { get; set; }
}
public class EnmSections : IEnumBase
{
public IEnumItem[] Items { get; private set; }
public EnmSections()
{
Items = new IEnumItem[]
{
new EnumItem
{
DisplayText = "Section1",
Items = new IEnumItem[]
{
new EnumItem { DisplayText = "TestA" },
new EnumItem { DisplayText = "TestB" }
}
},
new EnumItem
{
DisplayText = "Section2",
Items = new IEnumItem[]
{
new EnumItem { DisplayText = "Test1" },
new EnumItem { DisplayText = "Test2" }
}
}
};
}
}
drpSubsection.DataSource = Enum.GetNames(Type.GetType("Your.Namespace." + strType));
If the enums are in another assembly, (i.e. they're not in mscorlib or the current assembly) you'll need to provide the AssemblyQualifiedName. The easiest way to get this will be to look at typeof(Section1).AssemblyQualifiedName, then modify your code to include all the necessary parts. The code will look something like this when you're done:
drpSubsection.DataSource = Enum.GetNames(Type.GetType("Your.Namespace." + strType + ", MyAssembly, Version=1.3.0.0, Culture=neutral, PublicKeyToken=b17a5c561934e089"));