In response to this answer... Access MVC3 Model properties from Javascript in the View I'd like to know how I can construct the data for the view model in that example dynamically, without having to hardcode. i.e. I'd like to be able to do model.Values.Add(...)
There's already a dynamic object that you can add your values to...it's called the ViewBag.
There's no point in trying to roll your own since you're already losing the benefits of the strong typed model.
You can have a model that looks like this
public class MyViewModel()
{
private readonly List<string> _values = new List<string>();
public string[] Values { get { return _values.ToArray(); } }
public void AddValue(string value)
{
_values.Add(value);
}
}
Related
I'm trying to display list of items in XAML. I get the list from public API, convert it to the class I need and then I want to display it.
public static async Task PopulateListAsync(ObservableCollection<MyClass> myList) {
var listContainer = await GetListAsync();
foreach (var item in listContainer) {
//converting from one class to another, editing some properties and such
myList.Add(item );
}
}
and on the MainPage.cs I had
public ObservableCollection<MyClass> Value { get; set; }
public MainPage() {
this.InitializeComponent();
Value = new ObservableCollection<MyClass>();
}
private async void Page_Loaded(object sender, RoutedEventArgs e) {
await PopulateListAsync(Value);
}
And I displayed in the XAML fine.
But then I wanted to introduce filtering. So I get the data, convert them to some class and insert them to a list, which I then filter with LINQ (seems easier then filtering in ObservableCollection).
Basically I replaced the PopulateListAsync() with FormatListAsync() which instead of inserting the data directly into the ObservableCollection<>, returns a List<>. Then I have a "middle man" function
public static async Task PopulateListAsync(ObservableCollection<MyClass> myList) {
myList = new ObservableCollection<MyClass>(await FormatListAsync());
//filtering itself isn't implemented yet, but it would be placed here
}
I probably could just loop trough mylist and add it one by one into the ObservableCollection<>, but I feel like there surely is a better way.
I think I'm supposed to implement some PropertyChanged event or something like that, but I tried a few (this one for example), unsuccessfully. I don't think I quite understand how to implement it.
If you are assign new value for method parameter then you just change reference's copy to the collection and don't change source reference. You can read more about passing reference types as method parameters on MSDN.
Also, if you will change property that not implements INotifyPropertyChanged itself then you'll have no changes in UI because your view doesn't know about the changes.
In the simple and easy way you can manipulate source collection instead of creating new one. Just do something like
public static async Task PopulateListAsync(ObservableCollection<MyClass> myList)
{
// newList can be an List<MyClass> type, not ObservableCollection
var newList = await FormatListAsync();
// change displayed list with new data
myList.Clear();
foreach(var newValue in newList)
myList.Add(newValue);
}
The other option, you can implement INotifyPropertyChanged for your ViewModel and raise PropertyChanged event in the setter of Value property:
private ObservableCollection<MyClass> _value;
public ObservableCollection<MyClass> Value
{
get
{
return _value;
}
set
{
// I hope this line of code will convince you to give more clear variable name
if(value != _value)
{
_value = value;
NotifyPropertyChanged(nameof(Value));
}
}
}
Also, you'll need to assign Value directly in the PopulateListAsync():
public static async Task PopulateListAsync()
{
Value = new ObservableCollection<MyClass>(await FormatListAsync());
}
In general terms, a program I'm making involves storing a small number of entries (probably less than 30 at any given time) which can be categorized. I want to allow these entries to be seen but not altered from outside the class using them. I made a class called Entry which could be modified and another called ReadOnlyEntry which is a wrapper for an Entry object. The easiest way to organize these Entry objects it seems is to create a List<List<Entry>>, where each List<Entry> is a category. But then exposing that data in a readonly way became messy and complicated. I realized I would have to have one object of each of the following types:
List<List<Entry>> data;
List<List<ReadOnlyEntry>> // Where each ReadOnlyEntry is a wrapper for the Entry in the same list and at the same index as its Entry object.
List<IReadOnlyCollection<ReadOnlyEntry>> // Where each IReadOnlyCollection is a wrapper for the List<ReadOnlyEntry> at the same index in data.
IReadOnlyCollection<IReadOnlyCollection<ReadOnlyList>> readOnlyList // Which is a wrapper for the first item I listed.
The last item in the list would be exposed as public. The first lets me change entries, the second lets me add or delete entries, and the third lets me add or delete categories. I would have to keep these wrappers accurate whenever the data changes. This seems convoluted to me, so I'm wondering if there's a blatantly better way to handle this.
Edit 1:
To clarify, I know how to use List.asReadOnly(), and the stuff I proposed doing above will solve my problem. I'm just interested in hearing a better solution. Let me give you some code.
class Database
{
// Everything I described above takes place here.
// The data will be readable by this property:
public IReadOnlyCollection<IReadOnlyCollection<ReadOnlyList>> Data
{
get
{
return readOnlyList;
}
}
// These methods will be used to modify the data.
public void AddEntry(stuff);
public void DeleteEntry(index);
public void MoveEntry(to another category);
public void AddCategory(stuff);
public void DeleteCategory(index);
}
You can use List<T>.AsReadOnly() to return ReadOnlyCollection<T>.
Also, you're torturing the List<T> class storing the data the way you are. Build your own hierarchy of classes which store your individual lists.
.NET collections should support covariance, but they don't support it themselves (instead some interfaces support covariance https://msdn.microsoft.com/ru-ru/library/dd233059.aspx). Covariance means List<Conctrete> behaves like subclass of List<Base> if Concrete is subclass of Base. You can use interfaces covariation or just use casting like this:
using System.Collections.Generic;
namespace MyApp
{
interface IEntry
{
}
class Entry : IEntry
{
}
class Program
{
private List<List<Entry>> _matrix = null;
public List<List<IEntry>> MatrixWithROElements
{
get
{
return _matrix.ConvertAll(row => row.ConvertAll(item => item as IEntry));
}
}
public IReadOnlyList<List<IEntry>> MatrixWithRONumberOfRows
{
get
{
return _matrix.ConvertAll(row => row.ConvertAll(item => item as IEntry));
}
}
public List<IReadOnlyList<IEntry>> MatrixWithRONumberOfColumns
{
get
{
return _matrix.ConvertAll(row => row.ConvertAll(item => item as IEntry) as IReadOnlyList<IEntry>);
}
}
public IReadOnlyList<IReadOnlyList<IEntry>> MatrixWithRONumberOfRowsAndColumns
{
get
{
return _matrix.ConvertAll(row => row.ConvertAll(item => item as IEntry));
}
}
public void Main(string[] args)
{
}
}
}
Thanks to Matthew Watson for pointing on errors in my previous answer version.
You could make an interface for Entry which contains only getters; you would expose elements via this interface to provide read-only access:
public interface IEntry
{
int Value { get; }
}
The writable implementation would be simply:
public sealed class Entry : IEntry
{
public int Value { get; set; }
}
Now you can take advantage of the fact that you can return a List<List<Entry>> as a IReadOnlyCollection<IReadOnlyCollection<IEntry>> without having to do any extra work:
public sealed class Database
{
private readonly List<List<Entry>> _list = new List<List<Entry>>();
public Database()
{
// Create your list of lists.
List<Entry> innerList = new List<Entry>
{
new Entry {Value = 1},
new Entry {Value = 2}
};
_list.Add(innerList);
}
public IReadOnlyCollection<IReadOnlyCollection<IEntry>> Data => _list;
}
Note how simple the implementation of the Data property is.
If you need to add new properties to IEntry you would also have to add them to Entry, but you wouldn't need to change the Database class.
If you're using C#5 or earlier, Data would look like this:
public IReadOnlyCollection<IReadOnlyCollection<IEntry>> Data
{
get { return _list; }
}
I have a profile form that has a lot of user selections and I am sort of stumped on a good approach to validate what the user enters, when passing validation mapping those values to object properties.
For example I have a dictionary
public static Dictionary<string, string> objProfileSelections = new Dictionary<string, string>();
public static string MySelections(string key)
{
objProfileSelections.Add("1", "No Answer");
objProfileSelections.Add("3", "Less Than $25,000");
objProfileSelections.Add("5", "$35,000 to $50,000");
objProfileSelections.Add("7", "$50,000 to $75,000");
objProfileSelections.Add("9", "$75,000 to $100,000");
objProfileSelections.Add("11", "$100,000 to $150,000");
objProfileSelections.Add("13", "$150,000+");
objProfileSelections.Add("2", "No Answer");
objProfileSelections.Add("4", "Less Than $25,000");
objProfileSelections.Add("6", "$35,000 to $50,000");
objProfileSelections.Add("8", "$50,000 to $75,000");
objProfileSelections.Add("10", "$75,000 to $100,000");
objProfileSelections.Add("12", "$100,000 to $150,000");
objProfileSelections.Add("14", "$150,000+");
string item;
objProfileSelections.TryGetValue(key, out item);
return item;
}
Id like to pass in a list of key strings from the user and pass those items to populate an object. The issue is I don't know how to code it so it know which property to go to, I looked at reflection, but I couldn't find any examples that have a set dictionary of values that map to property names.
To make a bit more clear, when a user makes a selection it passes as a parameter in the dictionary, and the dictionary outputs the items. From key 1 comes value No Answer. If the user selected all the check boxes it would be value - (1,3,5,7,9,11,13). I need to extract those values when there is a matching key to a matching property. For example if the user clicks 1,5 but leaves the rest unchecked, how do I know which selections the user made? How do I get the program to know which property to populate based on the results?
*edit
some properties I would like it mapped to
public string MyAnnualIncome{ get; set; }
public List<string> InterestAnnualIncome{ get; set; }
So the first property would be taking one value, and the second property would be taking multiple values.
When a key matches a value comes out the dictionary, I would need the odd values going to MyAnnualIncome and the even values going to InterestAnnualIncome.
so no one is confused odd and even keys are set up for a purpose, odd numbers belonging to a certain group of properties and the even ones belonging to another based on the html selections (even being my selections, odd being what I am interested in)
*Update
Is there a way I can possibly use the keys like 1,3,5 and pass that into a list using the except extension method. Then take the results and use a method to convert the values from enumerated data types to strings?
Hopefully I understood your question.
I would add a small helper class (this is a solution which doesn't use reflection, but uses delegates instead):
public class PropertyModifier
{
private string text;
private Func<string> modifier;
public PropertyModifier(Func<string> modifier)
{
this.modifier = modifier;
}
public PropertyModifier With(string text)
{
PropertyModifier newModifier = new PropertyModifier(modifier);
newModifier.text = text;
return newModifier;
}
public void Modify()
{
modifier(Text);
}
}
Then I would rewrite your code and have the dictionary map to this class instead to string:
public static Dictionary<string, PropertyModifier> objProfileSelections = new Dictionary<string, PropertyModifier>();
public static MyUserProfile Profile; //Assuming this is the object you want to modify
public static string MySelections(string key)
{
PropertyModifier myIncome = new PropertyModifier(text => Profile.MyAnnualIncome = text);
PropertyModifier interestIncome = new PropertyModifier(text => Profile.InterestAnnualIncome.Add(text));
objProfileSelections.Add("1", myIncome.With("No Answer"));
objProfileSelections.Add("3", myIncome.With("Less Than $25,000"));
...
objProfileSelections.Add("2", interestIncome.With("No Answer"));
objProfileSelections.Add("4", interestIncome.With("Less Than $25,000"));
...
}
Then, when processing the user's selection, get the mapped PropertyModifier from the dictionary and call its Modify method.
I tried in this code to illustrate how you can modify the properties of the different classes that may compose a profile. Modifications are done by reflection only, i.e. just providing the class name, the property name that will vary in each class and the string value to be assigned to the property.
Not sure that it fits your expectations :(
Profile profile = new Profile() ;
profile.SetPropertyValue("hair","color","brown") ;
internal class Profile()
{
private Hair hair_ = new Hair();
private Job job_ = new Job ();
internal Hair hair { get { return hair_ ; } }
internal Job job { get { return job_ ; } }
private void SetPropertyValue(string profileItemName, string ItemPropertyName, string value)
{ // it is assumed that the different items (hair or job) of the Profile are accessible
// with a a property
// first find the Item object, i.e. hair or job
object itemObj = this.GetType().GetProperty(profileItemName).GetValue(this,null);
// assign to Item property the input value, e.g. hair.color=Brown
itemObj.GetType().GetProperty(ItemPropertyName).SetValue(itemObj, value, null);
}
}
internal class Hair()
{
private string color_ ;
private string style_ ;
internal string color { get { return color_ ; } set {color_ = value ; } }
internal string style { get { return style_ ; } set {style_ = value ; } }
}
I'm not even sure if I'm doing this correctly. But basically I have a list of objects that are built out of a class/interface. From there, I am binding the list to a DataGridView that is on a Windows Form (C#)
Here the list is a Sync list which will auto update the UI, in this case DataGridView.
Every thing works fine now, but now i would like to have the List should have an dynamic object, that is the object will have by default two static property (ID, Name), and at run time user will select remaining properties. These should be bind to the data grid. Any update on the list should be auto reflected in the grid.
I am aware that, we can use dynamic objects, but i would like to know , how to approach for solution,
datagridview.DataSource = myData; // myData is AutoUpdateList<IPersonInfo>
Now IPersonInfo is the type of object, need to add dynamic properties for this type at runtime.
public class AutoUpdateList<T> : BindingList<T>
{
private ISynchronizeInvoke _SyncObject;
private Action<ListChangedEventArgs> _FireEventAction;
public AutoUpdateList()
: this(null)
{
}
public AutoUpdateList(ISynchronizeInvoke syncObject)
{
_SyncObject = syncObject;
_FireEventAction = FireEvent;
}
protected override void OnListChanged(ListChangedEventArgs args)
{
try
{
if (_SyncObject == null)
{
FireEvent(args);
}
else
{
_SyncObject.Invoke(_FireEventAction, new object[] { args });
}
}
catch (Exception)
{
// TODO: Log Here
}
}
private void FireEvent(ListChangedEventArgs args)
{
base.OnListChanged(args);
}
}
Could you help out on this?
I guess the best way for you is 'to simulate' the properties. I guess the best way would be the ITypedList implementing, the great example is here.
Once I faced similar issue. For my case I've taken this approach. This just might be helpful for you.
Also, there is a way (it's not about anything 'dynamic') to have a base class with fulls set of properties you gonna use. But it won't work if you don't have all properties before the runtime.
I have a class that stores a list of dictionary entries. I want bind that to a datasource for gridview from codebehind.
Code for dictionary type of , representing ErrorMessage and failed field.
public partial class FailedFields
{
private Dictionary<string, string> Code_Error = new Dictionary<string, string>();
public void AddFailedField(string field, string message)
{
Code_Error.Add(field, message);
}
public Dictionary<string, string> GetFailedFields()
{
return Code_Error;
}
}
Code for List of Dictionary entries.
public partial class ErrorFieldsList
{
private static List<Order.FailedFields> ErrorList = new List<Slab.FailedFields>();
public void AddErrorField(Order.FailedFields errs)
{
ErrorList.Add(errs);
}
public List<Order.FailedFields> GetErrorMessages()
{
return ErrorList;
}
}
Running in Visual Studio debug mode, i can see the list has the error list, but i cannot get it to display in the gridview. Bellow is one of the many ways (the one that makes most sense) i tried to set the list as a datasource.
ErrorBoxGridView.DataSource = FailedRecords.GetErrorMessages(). ;
ErrorBoxGridView.DataBind();
Any idea where i am going wrong ?
Also, i don't want to specify a datasource in the aspx page because i only want to display this when the error occurs.
If interested why i am doing this to store error messages, have a look at this:link 1
Solved Here Related Question
I will document a complete project when i finish on the wiki.
This can not be done I think. What I'd do is:
Instead of using Dictionary<string, string> define a class that contains two public properties for field and message
Create an object data source for that class (using Visual Studios "Data Sources" window)
Have GetErrorMessages() return List<ErrorClass> instead of Dictionary
Assign that list to the binding source.
EDIT
This is to clarify things according to the latest comments. What you need is one class that contains the information for one error. For example:
public class ErrorInfo
{
public string Field { get { ... } }
public string Message { get { ... } }
}
After that you place a BindingSource on your form and (in code) set its DataSource property to a list of error message classes. For example:
private List<ErrorInfo> errorList = new List<ErrorInfo>();
errorList.Add(new ErrorInfo() { ... });
errorList.Add(new ErrorInfo() { ... });
errorList.Add(new ErrorInfo() { ... });
bindingSource.DataSource = errorList;
The data grid view is bound to the BindingSource. You should see data now. You can manually create columns and set them to the respective property names of your ErrorInfo class as well, but then you'd have to set dataGridView.AutoCreateColumns to false somewhere in your code.
Databind List of Dictionnary into a GridView
List<Dictionary<string,string>> resultSet = SOME List of Dictionaries...
DataGridView.DataSource = resultSet.Select(x => new {
fieldOne = x["key1"], fieldTwo = x["key2"]
}).ToList();
DataGridView.DataBind();
Now u can Bind fieldOne and fieldTwo in the DataGridView element...
Kindly check the Link for the precise ans...
Thanks
.NET provides a handy KeyValuePair<(Of <(TKey, TValue>)>) structure, that can be used in cases like this. That way you don't have to define your own class. HTH.
Or you could bind to the Value & Key properties of each Dictionary item:
ErrorBoxGridView.DataSource = FailedRecords.GetErrorMessages();
ErrorBoxGridView.DataTextField = "Value";
ErrorBoxGridView.DataValueField = "Key";
ErrorBoxGridView.DataBind();