I've got an issue with a list property that holds bookmarks. Before I started fiddling around it worked just fine.
I want the list to always be sorted from a-z when fetched and I want the list to be able to set to the value put in.
I am not sure why it won't work. Any suggestions on getting the latter to work, or any suggestions to sort the list in any other manner is greatly appreciated and welcome!
Here the bookmark list is being set from a database query:
model.Bookmarks = GetBookmarks().Select(b => new UIBookmark(b, DbHelper)).ToList();
This worked:
public List<UIBookmark> Bookmarks { get; set; }
This doesn't:
public List<UIBookmark> Bookmarks { get { return Bookmarks.OrderBy(b => b.Name).ToList(); } set { Bookmarks = value; } }
If you are not using auto-properties, you HAVE TO use a field to store your data.
private List<UIBookmark> _bookmarks;
public List<UIBookmark> Bookmarks { get { return _bookmarks.OrderBy(b => b.Name).ToList(); } set { _bookmarks = value; } }
Basicly, auto-properties do the same thing, you just don't have to write anything.
You will want to use a backing field instead of referencing the property itself in the getter and setter, like so:
private List<UIBookmark> _bookmarks;
public List<UIBookmark> Bookmarks { get { return _bookmarks.OrderBy(b => b.Name).ToList(); } set { _bookmarks = value; } }
MSDN has some good articles introducing the concepts of Properties and Auto-Properties that I would suggest reading up on too.
Related
I'm only at chapter 5 in "Essential C#" and not sure if i understand the difference correctly. I tried to make the model below to test one instance of everything in the properties chapter - and it works - but is the example acceptable use of the two ways one can implement properties or are there better ways?
using MarkdownSharp; // StackOverflow's md processor
public class Article
{
public string Headline { get; set; }
public string Content
{
get
{
return _content;
}
set
{
var md = new Markdown();
var html = md.Transform(value);
_content = html;
}
}
private string _content;
public DateTime Published { get; set; } = DateTime.Now;
}
This question may be better suited for codereview.stackexchange, although it's perhaps too tiny a snippet and to vague a question for that.
Personally, I shy away from magic properties that act in surprising ways. It tends to make for APIs that can be hard to use because they are surprising, even if they are somehow “clever” under the hood. You have a property where you set a different value than the one you get out. One thing where this can break would be the += operator, which suddenly would work in very weird ways with your Content property.
I'd probably go with something like
public class Article
{
private string content;
private string renderedContent;
public string Headline { get; set; }
public string Content
{
get { return content; }
set
{
content = value;
renderedContent = null; // reset cached rendered content
}
}
public string RenderedContent
{
get
{
if (renderedContent == null)
{
renderedContent = new Markdown().Transform(content);
}
return renderedContent;
}
}
public DateTime Published { get; set; } = DateTime.Now;
}
As for whether to use field-backed properties, or auto-properties, or computed properties ... that's up to you to decide based on what the property is supposed to do. Auto-properties are fine for simply storing and retrieving a value, e.g. Published or Headline here. You need the explicit backing field as soon as you do something more than just reading or writing it in the getter and setter, as shown here in Content. RenderedContent could be just a computed property, but I chose to cache the value after initial conversion because you kinda do the same. This pattern here doesn't convert the Markdown until it's actually needed, though.
I want to create a query with linq on my ObservableCollection but it doesn't really work how T tried it.
I have a Model Entry which has {note, information, isActive} as parameters. So I now want to simply just get all the Entries where isActive is true. I don't use it on my dataprovider (once the data gets loaded) because I need to load every entry into the program.
So I thought about to override the getter inside my entries ObservableCollection:
public ObservableCollection<Note> _entries { get; set; }
public ObservableCollection<Note> entries
{
get
{
return new ObservableCollection<Note>(from entry in this._entries
where entry.isActive == true
select entry);
}
set { this._entries = value; }
}
But as you might guess this doesn't work.
Regards
Try
get
{
List<Notes> list = _entries.Where(e=>e.isActive).ToList();
return new ObservableCollection<Note>(list) ;
}
Rather than editing it in the get, try updating the refinedEntries in the entries' setter. My Linq statement may need work but it encapsulates what I'm trying to suggest.
Essentially keep a copy of everything even the inactive records in entries and another collection to contain only the active records. In this case I'm calling it refinedEntries.
private ObservableCollection<Note> _entries;
public ObservableCollection<Note> entries
{
get{return _entries;}
set
{
_entries = value;
RefinedEntries = new ObservableCollection(_entries.Where(e=>e.isActive).Select(e => e));
}
}
public ObservableCollection<Note> refinedEntries {get;set;}
I would also suggest updating refinedEntries when CollectionChangedEvent fires. In this case the only time refinedEntries is updated is when entries is set to a new instance.
When you instantiate an new collection for entries, subscribe to its CollectionChangedEvent. For example if you instantiate the collection in the Model's constructor you could use the following..
entries = new ObservableCollection<Note>();
entries.CollectionChangedEvent += new NotifyCollectionChangedEventHandler((sender,args) =>
{
RefinedEntries = new ObservableCollection(_entries.Where(e=>e.isActive).Select(e => e));
//Notify the UI that an update has been made.
OnPropertyChanged("RefinedEntries");
});
I'm using EF6, and I'm wanting to move the initialisation of my collections to the Entity itself, so the code can be written once, the tutorials don't do this, just wondering if it's ok? I don't know enough about the Entity Frameworks under the hood stuff yet to know if this is ok.
For example:
[NotMapped]
private List<MySuggestion> _mySelections;
public virtual ICollection<MySuggestion> mySuggestions {
get
{
if (_mySelections == null)
{
_mySelections = new List<MySuggestion>();
}
return _mySelections;
}
set;
}
With the alternative being that the list be init'd as required in the Controller/Repository, with something like:
if (thing.mySuggestions == null){
thing.mySuggestions = new List<Suggestion> ();
}
That should work fine. You'll need to specify a body for the setter though...
set
{
_mySelections = value;
}
How to avoid redundant second query to database with using MVVM pattern on view model:
public class DataFormViewModel : INotifyPropertyChanged
{
private int companyId
public int CompanyId
{
get { return companyId; }
set
{
companyId = value;
RaisePropentyChanged("FindingStatuses");
RaisePropentyChanged("StatusCount");
}
}
public List<FindingStatus> FindingStatuses
{
get
{
return FindingStatusService.GetAvalableStatuses(CompanyId);
}
}
public int StatusCount
{
get { return FindingStatuses.Count; }
}
}
i.e. when CompanyId was changed by DataBinder FindingStatuses will be executed and then StatusCount will be executed, that will execute FindingStatuses again.
I'm not sure I'd bind the property directly to a database operation in the first place. Why not have a local List<FindingStatus> representing the "last fetched" statuses, and then explicitly refresh it?
Apart from anything else, property access is usually expected to be reasonably cheap - making a database call every time you access either of those properties sounds like a bad idea to me.
Like Jon already mentioned, accessing properties are expected to be cheap, something you can do a thousand times without any sideeffect.
I would cache the result of your database access and return the cached object on any following request. Ie
private IList<FindingStatus> _findingStatuses;
public IList<FindingStatus> FindingStatuses
{
get
{
if (_findingStatuses == null)
{
_findingStatuses = FindingStatusService.GetAvalableStatuses(CompanyId);
}
return _findingStatuses;
}
}
And then you would of course have to clear your cache before raising the notification
public int CompanyId
{
get { return companyId; }
set
{
companyId = value;
_findingStatuses = null;
RaisePropentyChanged("FindingStatuses");
RaisePropentyChanged("StatusCount");
}
}
The best way to avoid multiple (and useless) queries to the database, is implement a simple cache layer in the Data Access Layer.
1- Ask the cache if he already has an updated result
2- Else query the database
Here is a cache class you can try: http://www.codeproject.com/KB/recipes/andregenericcache.aspx
I'm new to LINQ and I've been at this for hours now. I have a List<> of objects where one of the objects properties is a List of selected categories. I also have, outside of the objects, a List representing a subset of categories and I want to return all objects which contain at least one category that is also in the subset as illustrated in the following pseudo code (not my actual code)
List<string> subset = cat, dog, mouse
List<myclass> myclasses =
{name:alphie, category:[cat,elephant]},{name:sally, category:[fish]}, {name:bob, category:[dog, mouse]}
In the above example I need to return alphie and bob since they both have at least one category that's in my subset.
The only solution so far is to get a list of both and then use expensive foreach loops to go through and compare. I'm sure LINQ must provide a more efficient way to achieve the same?
More details (I think my pseudo code is not detailed enough)
public class RadioProgram {
...
private List<string> _category = new List<string>();
public List<string> Category { get { return _category; } set { _category = value; } }
...
}
public class Category {
...
private string _categoryName = "";
private List<Category> _subCategories = new List<Category>();
public string CategoryName { get { return _categoryName; } set { _categoryName = value; } }
public List<Category> SubCategories { get { return _subCategories; } set { _subCategories = value; } }
...
}
I have a method, GetCategories(string parentCategory), that returns all child categoryNames as List. Each radioProgram.Category (yes, name needs to be refactored to plural) is itself a List and may contain zero, one or more categoryNames. I'm getting my master list of radioPrograms and I want to return a subset that contain where each one contains at least one categoryName that matches the set from GetCategories.
I'm trying to avoid changing the architecture of the application (which is a potential solution) as it means a lot of refactoring of existing functionality AND I think this happens to be a good exercise for tackling and understanding LINQ.
One thing you could use is
myclasses
.Where(o => o.category.Any(c => subset.Contains(c)));