Could someone help me below?
It seems Set is not called. How can I get around this?
Note that _students is set as the selectedObject of a property grid. So adding is done in the UI.
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
}
public class Record
{
List<Student> _students = new List<Students>();
public List<Student> Students
{
get
{
return _students;
}
set
{
// track changes here...
MessageBox.Show("value set!"); // this doesn't get called
_students = value;
}
}
}
I think you're having an issue with what set does with a list. You'll never see the message on adding a student to Record.Students, only when you set the list.
void Main()
{
Student s = new Student() {
Name = "fred",
Age = 10
};
List<Student> _s = new List<Student>();
_s.Add(s);
Record r = new Record();
r.Students = _s; //You'll get a message here
r.Students.Add(s); //No message here
}
// Define other methods and classes here
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
}
public class Record
{
List<Student> _students = new List<Student>();
public List<Student> Students
{
get
{
return _students;
}
set
{
// track changes here...
MessageBox.Show("value set!");
_students = value;
}
}
}
Right now, you just set _students.
If you want that setter to execute, you're gonna have to go Students = new List<Student<(); instead of _students = new List<Student>();.
Related
Is it possible to have a (EF6) Linq select statement instantiate a class, such that a property's set accessor is triggered with the values returned from the Linq statement?
I have tried code (similar) to that below, but despite the query returning data, the set's value is an empty list. I am assuming that Linq creates a new instance of MyModel, and then adds the records from the record set.
Is it possible to trigger doSomething() after MyList is fully populated, but from within the scope of MyModel (i.e. not adding a subsequent call after context.SomeEntities.Select(...))?
public class MyModel{
private List<string> _myList;
public List<string> MyList {
get { return _myList; }
set { _myList = value; doSomething(); }
}
private void doSomething() {...}
}
..
context.SomeEntities.Select(x => new MyModel { MyList = x.YourList });
The answer to both of your questions is "Yes." The following worked for me:
class Program
{
static void Main(string[] args)
{
Context context = new Context();
List<MyModel> myModelsList = context.Products.Include("Names").AsEnumerable().Select(x =>
{
MyModel model = new MyModel();
model.MyList = x.Names.Select(pn => pn.Name).ToList();
return model;
}).ToList();
}
static void CreateAndSeedDatabase()
{
Context context = new Context();
Product product1 = new Product() { Names = new List<ProductName> { new ProductName { Name = "1" } } };
Product product2 = new Product() { Names = new List<ProductName> { new ProductName { Name = "2" } } };
context.Products.Add(product1);
context.Products.Add(product2);
context.SaveChanges();
}
}
public class Context : DbContext
{
public Context()
{
Database.SetInitializer<Context>(new CreateDatabaseIfNotExists<Context>());
Database.Initialize(true);
}
public DbSet<Product> Products { get; set; }
public DbSet<ProductName> ProductNames { get; set; }
}
public class Product
{
public int ProductId { get; set; }
public List<ProductName> Names { get; set; }
}
public class ProductName
{
public int ProductNameId { get; set; }
public string Name { get; set; }
}
public class MyModel
{
private List<string> _myList;
public List<string> MyList
{
get { return _myList; }
set { _myList = value; doSomething(); }
}
private void doSomething()
{
Console.WriteLine(_myList[0]);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Assignment5
{
public class Person
{
public string Name { get; set; }
public DateTime BirthDate { get; set; }
}
public class Student : Person
{
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public static int countS = 0;
public static List<string> studentlist = new List<string>();
public Student()
{
studentlist.Add(Name);
countS++;
}
public static int GetActiveInstances()
{
return countS;
}
}
class MainProgram
{
static void Main(string[] args)
{
// Instantiate three Student objects.
Student Student1 = new Student();
Student Student2 = new Student();
Student Student3 = new Student();
Student1.Name = "John";
Student2.Name = "Joe";
Student3.Name = "Jacob";
for (int i = 0; i < Student.studentlist.Count; i++) // Loop with for.
{
Console.WriteLine(Student.studentlist[i]);
}
Console.WriteLine("Press any key to continue . . . ");
Console.ReadKey();
}
}
}
Hi guys. What I have in mind is that I want to automatically store every student being initiated in an array/list that I created and eventually, I want to output these students in the console.
Can anyone enlighten me what I did wrong on my program?
Supposedly it will output the 3 names I declare. What I have on the output for the posted program are all blank.
**Next Related Question **
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Assignment6
{
public class Person
{
public string Name { get; set; }
public string Address { get; set; }
public virtual void GetInfo()
{
Console.WriteLine("Name: {0}", Name);
Console.WriteLine("Address: {0}", Address);
}
}
public class Student : Person
{
public void SetStudentInfo(string name, string address)
{
Name = name;
Address = address;
}
}
public class Course //class represents university course
{
private ArrayList studentList = new ArrayList();
public ArrayList StudentList
{
get { return studentList; }
set { studentList = value; }
}
//how can I implement this such that I can have the StudentList be updated and printed
// out to the console from the main
public void ListStudents()
{
foreach (Student i in StudentList)
{
Console.WriteLine(i.ToString());
}
}
}
class MainProgram
{
static void Main(string[] args)
{
var Student1 = new Student { Name = "John" };
var Student2 = new Student { Name = "Joe" };
var Student3 = new Student { Name = "Jacob" };
Course course1 = new Course();
course1.StudentList.Add(Student1);
course1.StudentList.Add(Student2);
course1.StudentList.Add(Student3);
course1.ListStudents();
Console.WriteLine();
Console.WriteLine("Press any key to continue . . . ");
Console.ReadKey();
}
}
}
I have this code and I want to output every student in my arraylist, the foreach loop should be on the course class. Still, the code is connected on my question so I just ask it here. Can anyone help me revise it? thanks
What I do not get is these line:
public static int countS = 0;
public static List<string> studentlist = new List<string>();
public Student()
{
studentlist.Add(Address);
countS++;
}
What I would suggest is to move these out so that the class is something like this:
public class Person
{
public string Name { get; set; }
public DateTime BirthDate { get; set; }
}
public class Student : Person
{
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
}
And that main is something like this:
static void Main(string[] args)
{
// Instantiate three Student objects.
Student Student1 = new Student();
Student Student2 = new Student();
Student Student3 = new Student();
Student1.Name = "John";
Student2.Name = "Joe";
Student3.Name = "Jacob";
var studentlist = new List<Student>{Student1,Student2,Student3};
foreach (var student in studentlist)
{
Console.WriteLine(student.Name);
}
Console.WriteLine("Press any key to continue . . . ");
Console.ReadKey();
}
Instead of adding a property that hasn't been set yet (which is what you're currently doing in the default constructor - you're adding the Name property before it's been set), you can add a reference to the class instance using the this keyword, so the properties of the items in your list (like Name or Address) get updated when they are set on the class instance.
Also, you don't need a separate variable to keep track of the number of students, since you can just use the Count property of the list.
Here's a way you can do this:
public class Student : Person
{
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public static List<Student> AllStudents = new List<Student>();
public Student()
{
AllStudents.Add(this);
}
public static int GetActiveInstances()
{
return AllStudents.Count;
}
}
Usage:
public static void Main()
{
var student1 = new Student {Name = "John"};
var student2 = new Student {Name = "Joe"};
var student3 = new Student {Name = "Jacob"};
foreach (var student in Student.AllStudents)
{
Console.WriteLine(student.Name);
}
}
Output:
JohnJoeJacob
UPDATE
One way you can protect your internal list, yet still let others query it, would be to make the list private, and then expose a public property that returns a copy of the list, which prevents people from affecting your private instance if they call .Add() or .Remove() on it, or try to set it to a new List<Student>.
Here's an example:
public class Student : Person
{
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
// This is the "official" list. It's private so cannot be changed externally
private static readonly List<Student> StudentList = new List<Student>();
// This property returns a COPY of our private list
public static List<Student> AllStudents
{
get
{
var copyOfList = new List<Student>();
copyOfList.AddRange(StudentList);
return copyOfList;
}
}
public Student()
{
// Add the student to our private list
StudentList.Add(this);
}
public static int StudentCount()
{
// Return the count from our private list
return StudentList.Count;
}
}
So I'm trying to build a small cookbook application using WPF and MVVM light. I've run into a situation where I'm binding a List from the model to the view model. And it works fine for displaying and removing items, but when adding items I couldn't get the display to update.
I came across ObserableCollections which seemed to be just what I wanted, but I'm not sure I'm using them correctly because it seems wrong to be creating a new OC every time. How am I supposed to be retrieving an observable collection when the model is using a list?
Model(s):
public class Recipe
{
public int Id { get; set; }
public string Title { get; set; }
public List<RecipeIngredient> Ingredients { get; set; }
}
public class RecipeIngredient
{
// ... //
}
ViewModel:
public Recipe SelectedRecipe
{
get
{
return this.selectedRecipe;
}
set
{
this.selectedRecipe = value;
RaisePropertyChanged("SelectedRecipe");
RaisePropertyChanged("RecipeIngredients");
}
}
public ObservableCollection<RecipeIngredient> RecipeIngredients
{
get
{
return new ObservableCollection<RecipeIngredient>(selectedRecipe.Ingredients.ToList());
}
}
public RelayCommand<EventArgs> AddIngredientCommand { get; private set; }
public RelayCommand<string> DeleteIngredientCommand { get; private set; }
private void AddIngredient(EventArgs eventArgs)
{
SelectedRecipe.Ingredients.Add(new RecipeIngredient() { Name = "New Ingredient" });
RaisePropertyChanged("RecipeIngredients");
}
private void DeleteIngredient(string name)
{
SelectedRecipe.Ingredients = SelectedRecipe.Ingredients.Where(i => i.Name != name).ToList();
RaisePropertyChanged("RecipeIngredients");
}
public MainViewModel()
{
DBController db = new DBController();
recipes = db.GetRecipeList();
RecipeSelectionChangedCommand = new RelayCommand<SelectionChangedEventArgs>((args) => RecipeSelectionChanged(args));
SaveRecipeCommand = new RelayCommand<EventArgs>((args) => SaveRecipe(args));
AddIngredientCommand = new RelayCommand<EventArgs>((args) => AddIngredient(args));
DeleteIngredientCommand = new RelayCommand<string>((args) => DeleteIngredient(args));
}
Am I way off track here?
Should have read more carefully. If you're displaying the selected recipe's ingredients in an alternate view, you should be using data binding in the view <ListBox ItemsSource="{Binding SelectedRecipe.Ingredients}"/> You could consider using linq to entities (Entity Framework) for ORM..
public class RecipeVM
{
public RecipeVM(Recipe r)
{
recipe = r;
}
Recipe recipe;
public int Id
{
get
{
return recipe.Id;
}
set
{
PropertyChanged("Id");
recipe.id = value;
}
}
public string Title
{
get
{
return recipe.Title;
}
set
{
PropertyChanged("Title");
recipe.Title = value;
}
}
ObservableCollection<RecipeIngredient> ingredients;
public ObservableCollection<RecipeIngredient> Ingredients
{
get
{
if (ingredients == null)
ingredients = new ObservableCollection<RecipeIngredient>(recipe.Ingredients);
return ingredients;
}
set
{
PropertyChanged("Ingredients");
ingredients = value;
}
}
}
You'll need to modify that a bit if you want to keep the collections in sync though..
I have a collection of objects that I want to sort alphabetically by their name property.
I have tried the following:
List<Item> itemsToSort = dataProvider.Items.ToList();
List<Item> sortedItems = itemsToSort.OrderBy(x=>x.Name).ToList();
Which doesnt work. The items are still listed in the same way as before and not alphabetically.
EDIT
Here is a more complete sample:
Class:
public class MeasureStation
{
#region Properties
public int ID
{
get { return _measureStation.ID; }
set { _measureStation.ID = value; }
}
[Required(ErrorMessage = "Navn skal udfyldes")]
public String Name
{
get { return _measureStation.Name; }
set { _measureStation.Name = value; }
}
public DateTime? DateEstablished
{
get { return _measureStation.DateEstablished; }
set { _measureStation.DateEstablished = value; }
}
public DateTime? OperationPeriodStart
{
get { return _measureStation.OperationPeriodStart; }
set { _measureStation.OperationPeriodStart = value; }
}
.
.
and so on...
}
The query is:
measureStations = dataProvider.MeasureStations.ToList();
var orderedMeasureStations = measureStations.OrderBy(x => x.Name);
When taking a look at the orderedMeasureStations query result, it looks like the following:
entry starting with:
F...
S...
a...
L...
So it is obviously not sorting by name.
I do not see how your class MeasureStation will ever work
What is _measureStation, is it this?
If it is, Then it should look like, note that the property cannot have the same name as its respective private member
public class MeasureStation
{
private int id;//private is optional as it is default
public int ID
{
get { return this.id; }
set { this.id = value; }
}
private String name;//private is optional as it is default
public String Name
{
get { return this.name; }
set { this.name = value; }
}
}
Though, it is equivalent to the class with auto-properties:
public class MeasureStation
{
public int ID {get;set;}
public String Name {get;set;}
}
So, I run against both of them
private static void Main(string[] args)
{
List<MeasureStation> itemsToSort
= new List<MeasureStation>()
{
new MeasureStation() {ID = 01, Name = "Bbbb"},
new MeasureStation() {ID = 01, Name = "Aaaa"},
new MeasureStation() {ID = 01, Name = "Cccc"}
};
List<MeasureStation> sortedItems = itemsToSort.OrderBy(x => x.Name).ToList();
Console.WriteLine("******itemsToSort*****");
foreach (var item in itemsToSort)
Console.WriteLine(item.Name.ToString());
Console.WriteLine("******sortedItems*****");
foreach (var item in sortedItems)
Console.WriteLine(item.Name.ToString());
Console.ReadLine();
}
having gotten ordered output:
******itemsToSort*****
Bbbb
Aaaa
Cccc
******sortedItems*****
Aaaa
Bbbb
Cccc
When i have declaration like:
class Professor
{
string profid;
public string ProfessorID
{
get { return profid;}
set { profid=value;}
}
student st;
}
class student
{
string name;
string id;
public string Name
{
get { return name;}
set { name=value; }
}
public string StudentID
{
get { return id;}
set { id=value; }
}
}
public void GetDetails()
{
Professor prf=new Professor(){ ProfessorID=1, how to initialize student here?};
}
Inside GetDetails() how can i initialize student ?
First make it accessible:
public student Student { get; set; }
then something like:
Professor prf = new Professor()
{
ProfessorID = "abc",
Student = new student { Name = "Marc", StudentID = "def" }
};
Note that if the property is get-only:
private readonly student _student = new student();
public student Student { get { return _student; }}
Then you can use the alternative syntax (which sets properties without attempting to change the student reference):
Professor prf = new Professor()
{
ProfessorID = "abc",
Student = { Name = "Marc", StudentID = "def" }
};
Your Professor class will need a property setter for the student, at which point you can write:
public void GetDetails()
{
Professor prf = new Professor {
ProfessorID = "1",
Student = new Student { Name = "Jon", StudentID = "1" }
};
}
Without that property, nothing in the Professor class will set the st variable at all.
Note that because in both cases we're only using the parameterless constructor, I've removed the explicit () from the object initializer.
Further note: automatically implemented properties can make your code a lot shorter:
class Professor
{
public string ProfessorID { get; set; }
public Student Student { get; set; }
}
class Student
{
public string Name { get; set; }
public string StudentID { get; set; }
}
You should make property Student in Professor:
class Professor
{
string profid;
public string ProfessorID
{
get { return profid; }
set { profid = value; }
}
student st;
public student Student { // New property
get { return st; }
set { st = value; }
}
}
class student
{
string name;
string id;
public string Name
{
get { return name; }
set { name = value; }
}
public string StudentID
{
get { return id; }
set { id = value; }
}
}
public void GetDetails(){
Professor prf=new Professor(){ ProfessorID="1", Student = new student()};
}
You need an accessor for your student within Professor
class Professor
{
string profid;
public string ProfessorID
{
get { return profid;}
set { profid=value;}
}
public Student {
get { return st;}
set { st=value;}
}
student st;
}
public void GetDetails()
{
Student s = new Student();
s.StudentId = someId;
s.name = someName;
Professor prf = new Professor { ProfessorID=1, Student = s;};
}
However, your current model is 1 Prof : 1 Student, are you sure this is what you want?
Following up on John's answer:
You want parentheses, not brackets, but a public constructor is typically the right approach. The other way to do it is a no-argument constructor with public properties.