In my MonoDevelop project I have an iPhone app. I have two different views. Each view contains a UITable. For view 1 I have class 1 hooked to the UITable as Datasource 1. For View 2 I have a class 2 hooked up as Datasource 2. Both classes (i.e. Datasources) feed the tables with data. View 2 also has a custom cell and because of this loads asynchronous.
I get the data from 2 XML files using linq to XML. Everything works and the data loads great. What I need to do know is to load data in Datasource 2 based on the selection made in View 1. To do this I need to pass an ID from view 1 to Class(Datasource) 2. Problem.
I have tried just about everything I know but I just can't get it right.
The correct solution according to me:
I have created another class called SelectedRound with two properties. Code:
using System;
namespace xxxxx
{
public class SelectedRound
{
public string RoundID { get; set; }
public string Date { get; set; }
}
}
When I set RoundID in class 1 then I can access it in class 1. Trying to access it in class 2 however, returns nothing or null. Why would this happen? Could it be because Class(Datasource) 2 is loading asynchronously? Should I instantiate the SelectedRound class in some global way? If so how? AppDelegate maybe? (I am struggling to do that as well).
It seems pointless to me that setting and getting a simple string variable is difficult.
This feels like it is all about how you are passing the SelectedRound instance from the first view to the second.
As a very quick and dirty solution you could just use a singleton or could just use a static class:
public static class SelectedRound
{
public static string RoundID {get;set;}
public static string Date {get;set;}
}
For a more sophisticated pattern, then try overriding the constructors of one or both of your two view controllers in order to pass them a shared instance of your non-static class.
The view controllers may feel foreign to you right now - but they are just c# classes - so feel free to extend them by writing overrides, new methods and properties.
Related
I have created a class to store data from API calls I am making. It returns JSON with some meta information, and then an array of data depending on the call being made. The meta information will always have the same fields, so I have created a "Root" class for this, but the data will be different depending on the call being made, so I have created different classes for each type of data, e.g. user data, company data, etc. As shown below, I currently have the "data" property set to a list of objects, but I am trying to figure out the best way to incorporate the different types of data that can be returned, since it will vary based on the call being made.
Right now I have the data saved as a list of objects, but I would like this to change depending on what data I am receiving. Like, if I am retrieving users, I would like for it to be a list of users.
What is the ideal way to accommodate for this? The only way I can think to do it now is to create a different "Root" class for every type of data I am expecting to receive, but that doesn't feel like it should be the most concise way to do it. I was looking into making this a factory design pattern but I wasn't sure that it fit this scenario.
Just use a generic base class:
public abstract class ApiCallResult<T>
{
// With your properties
// public int Limit { get; set; }
// [...]
//
public IEnumerable<T> Data { get; set; }
}
Then define a result per api call.
public class UserApiCallResult : ApiCallResult<User>
{
}
Created a small working example here:
dotnet fiddle
The Problem
Often controller classes (MVC, MVVM, MVP) that manipulate views have access to a multitude of services. The purpose of one of these services is to update the controller classes with data that is pertinent to the controller.
Take this class for example:
public sealed class RestaurantInformation
{
public IEnumerable<Networking.Models.ServerModels.Restaurant> NearestRestaurants { get; internal set; }
public IEnumerable<Networking.Models.ServerModels.Restaurant> NewestRestaurants { get; internal set; }
public IEnumerable<Networking.Models.ServerModels.Category> Categories { get; internal set; }
}
Whenever the service receives updated information from the network regarding Categories, NewestRestaurants or NearestRestaurants, it packages all of the data into an object which has the class type RestaurantInformation and sends it to the controller class to pass to the view.
I decided to put my C grade in my art GCSE to good use and construct diagrams to aid your understanding of my problem. (Apologies for what you are about to see.)
As you can now see, the flow is as follows:
The view loads which in turn calls the RestaurantViewControl.
The RestaurantViewControl then calls the RestaurantService to retrieve the new categories from the API.
The API returns the new categories to the RestaurantService. (You can see here the restaurant service now has a list that contains B).
The RestaurantService then notify's the RestaurantViewControl using the class above with the new list of categories!
We must now update the list of categories in the RestaurantViewControl in the most efficient way possible with the new items.
I am currently clearing the categories list and then replacing all the values with the new list. The two things I want to know are:
What is the most efficient way to detect a change in the Categories List object?
What is the most efficient way to update the categories list which may still contain objects that are completely valid in that list.
Seems like you have a straight forward issue. You will have a services layer that calls when you show the restaurant list page.
So your collectionView/listView just displays the list of items in the view cell based on that data. One example https://almirvuk.blogspot.com/2019/07/lets-play-with-collectionview-layouts.html?m=1
Usually you’ll just do a check for changes on the first time you visit the page, pull to refresh, or if you set up caching-after a set time when the cache expires.
I seem to be running into a weird issue and after hours of head scratching, I seem to have narrowed the issue down to a combination of partial classes and virtual properties. When I override a property that's in a partial class, sitting in a separate file, MVC duplicates the fields on my view. I am using Visual Studio 2013 and the issue can be duplicated by following these steps:
Open Visual Studio and create a new Project. Choose Web under the categories, then choose "ASP.NET Web Application". I am targeting .NET 4.5.
Choose "Empty" from the template selection, then check the MVC checkbox so it adds the core folders and references.
Once the project is created, right-click on the Models folder and create a new class called MyModel.cs.
Add these lines to the new file:
public abstract partial class MyOriginalModel
{
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
}
public partial class MyModel : MyOriginalModel
{
}
Now right click on the Models folder again and create another new class called MyModelCustom.cs.
Add these lines to the file:
public partial class MyModel
{
[System.ComponentModel.DisplayName("First Name")]
[System.ComponentModel.DataAnnotations.Required]
public override string FirstName
{
get
{
return base.FirstName;
}
set
{
base.FirstName = value;
}
}
[System.ComponentModel.DisplayName("Last Name")]
[System.ComponentModel.DataAnnotations.Required]
public override string LastName
{
get
{
return base.LastName;
}
set
{
base.LastName = value;
}
}
}
Now build the project, then right click on the Controllers folder and add a new controller. Choose "MVC 5 Controller with read/write actions" and call it NamesController. Right click on the Create method and go to "Add View". Under the template dropdown, choose Create and for the Model Class dropdown, choose MyModel.
Once MVC creates the template, you will see that it adds First Name and Last Name twice. The issue seems to be related to partial classes because if I move the contents of MyModelCustom.cs into MyModel.cs, everything works fine. However, its not just partial classes. If I create a new property (versus overloading one) in the partial class, it does not duplicate that property. So it seems to be a combination of partial classes and overriding virtual properties.
Can someone please confirm if this is a bug or if I am doing something wrong?
It is a bit of both. Bug or not, if MVC is scaffolding incorrectly, you will either have to constantly fight the framework or change your approach to the problem.
As a general rule, I've found that when you have to fight the MVC framework to make it behave the way you want, then it is far easier to change your approach to the problem. Otherwise, you will end up fighting that particular battle repeatedly until you eventually comply. Take it from someone who's learned that lesson the hard way.
With easier approaches in mind, here are a few things you could try instead:
If you are overwriting a lot of properties, create separate classes with common names for properties (FirstName, LastName). Then use Best way to clone properties of disparate objects to marshall the data between objects.
You could also use Fody PropertyChange listeners to handle whatever logic is needed when these values are changed thereby eliminating the need for the partial overrides entirely.
A final option would be to override the scaffolding templates to skip overridden properties. Not sure how you would detect that though.
Take a look at CodePlex source for MvcScaffolding EnvDTETypeLocator.cs
/// <summary>
/// Out of a set of CodeType instances, some of them may be different partials of the same class.
/// This method filters down such a set so that you get only one partial per class.
/// </summary>
private static List<CodeType> PickArbitraryRepresentativeOfPartialClasses(IEnumerable<CodeType> codeTypes)
{
var representatives = new List<CodeType>();
foreach (var codeType in codeTypes) {
var codeClass2 = codeType as CodeClass2;
if (codeClass2 != null) {
var matchesExistingRepresentative = (from candidate in representatives.OfType<CodeClass2>()
let candidatePartials = candidate.PartialClasses.OfType<CodeClass2>()
where candidatePartials.Contains(codeClass2)
select candidate).Any();
if (!matchesExistingRepresentative)
representatives.Add(codeType);
} else {
// Can't have partials because it's not a CodeClass2, so it can't clash with others
representatives.Add(codeType);
}
}
return representatives;
}
}
:
:
1) PickArbitraryRepresentativeOfPartialClasses, the method uses Linq any() to confirm that the codeType as CodeClass2 has members.
CodeClass2 is the partial class type of EnvDTE, Visual Studio's core Automation library responsible for IDE code generation (Design Time Reflection).
2) If the class cast as CodeClass2 does have members, the class is added to the representatives
3) When the partial class is evaluated, each file will be visited within a distinct context (often leading to a consolidation of elements that should be overridden)
An interesting distinction between Run Time Reflection and Design Time Reflection: sic
An ASP.NET control has two distinct sets of functionality for when it is executed at run-time inside a page or used at design-time inside a host designer. Run-time capabilities determine, based on configuration, the markup that is output by the control. The design-time capabilities, instead, benefit of a visual designer such as Microsoft Visual Studio 2005. Design-time capabilities let the page author configure the control for run-time in a declarative and WYSIWYG (what-you-see-is-what-you-get) manner.
Conclusion:
MVC Scaffolding does use reflection, but it is the much less reliable Design Time Reflection.
Design Time Reflection is not the same as Run Time reflection. A fully compiled Class is a final result of inheritance resolves and partials combined and priority resolved. Design Time Reflection makes best guesses about how to work with complex, multi-part types.
If you want to rely on Scaffolding, better not to push it's limits. When you get errors like this, try simplifying your ViewModels:
Try consolidating your partial classes
Try removing your abstracts / virtuals
I am about to upgrade our software from ASP.NET WebForms to .NET MVC. All over the web it shows how to create a view based on a model, which is fine.
In this project the users can hide properties of the model to generate a view suitable for them, yet another client in another website and hide other properties.
The code is all the same, but i would like to know if there is a way to hide/show properties of a model based on a condition easily, hopefully without having a lot of IF statements all over my views.
Example - How can 1 client see only name and town, yet another client see all 3 properties. Just need to show based on a condition.
public class MyObject() {
public property name { get; set; };
public property town { get; set; };
public property customText { get; set; }
public MyObject() {}
}
NOTE: Users can also determine the order of these properties, can i do that as well easily ?
Just to say that creating separate views is not possible. The above is a very simple example of a model with properties. Our models can have about 100 properties, and the user can turn these on and off whenever they like, so it needs to be able to be done dynamically
Is there a way of creating a ViewModel on the fly?
Thanks in advance
Create a Property class or similar and model you data appropriately:
public class Property
{
public string Name {get;set;}
public bool Visible {get;set;}
public int Order {get;set;}
}
Then your view model can be similar to your example:
public class ViewModel
{
public Property Name {get;set;}
public Property Town {get;set;}
public Property CustomText {get;set;}
}
Well you cannot bind multiple models to your view.Obviously you have to do workaround in your view based on user roles.
Or else create a seperate model and view for each user roles.
I have been working on a project called Dynamic MVC.
http://dynamicmvc.com
It currently does not do what your asking. The functionality is already there, it is just not exposed the way you need it. However, if you are interested I will add the functionality so you can pass the properties you want to display in the querystring. Eventually, a customizable dynamic view will generate your page for you without any coding required. Also, the order of the properties would determine the order on your page. This would work for any model with the DynamicEntity attribute.
Let me know if your interested and I can include it in the next release.
I am trying to find an effective way to databind computed fields of an Entity Framework model in winforms. I am using Visual Studio 2008 and .NET framework 3.5. An example would be for EntityX, say I have columnA and columnB, and I want a computed property named sumAB. The way I have been doing this has been with partial classes:
public partial class EntityX
{
public int sumAB
{
get
{
return this.columnA + this.columnB;
}
}
}
I then am using visual studio to add EntityX as a data source, so I can use the automatic drag and drop data binding. The issue that I am having is that the computed properties are not appearing under the Data Source fields. I am looking for a way to have the automatic databinding of computed fields.
I know I could do this manually, but then I would have to also manually write all of the binding code to refresh the field when columnA or columnB are changed. I also do not have access to make this field computed on the SQL server side either.
Does anyone know of any ways to accomplish this or any other similar directions to persue?
Thanks!
UPDATE
I tested this on another machine, using Visual Studio 2010 and .NET 4, and I am still receiving the same behavior. Interestingly, I can manually create a textbox and add a databinding, and it will work fine, as below:
sumABTextBox.DataBindings.Add(
new System.Windows.Forms.Binding("Text", EntityXBindingSource, "sumAB", true));
It also worked if I placed the property in the .edmx file, but this is not desirable, as it will be wiped any time the database is updated.
Any other ideas?
UPDATE 2
Still no solution... I had to use alternatives in my code to meet deadlines. I am still very interested in this if anyone finds an answer...
Sounds strange to me. Because I use the same approach in my project (Entity Framework, Self Tracking Entities, WCF, Winforms).
I constructed a simple winforms applciation to test it and the "computed" property just shows up in the databindings.Text property of a textbox control.
I created a simple class:
public partial class Test
{
public int A { get; set; }
public int B { get; set; }
public Test()
{
}
}
public partial class Test
{
public int AB
{
get { return A * B; }
}
}
Added a bindingsource to a form (with datasource pointing to an object of type Test) and three textboxes binded to the bindingsource and the properties: A, B and AB. In the constructor of the form I created an instance of test, populated values for A and B, set bindingsource.DataSource to the created instance and thinks were groovy on the form ;)
This simple test case would be no different from your situation, other than that you work with entities which are off-course just Objects. I really can't see the problem from your description...Any further comments could help me help you further...
I basically just asked the same question (WPF not WinForms) yesterday - Show Computed Property in Entity Framework and WPF UI .
In short, I couldn't find any automatic support. I had to create the columns in my DataGridView for each computed property. Then, to let the DataGridView know that those properties have updated, I have to call OnPropertyChanged("ComputedPropertyName") in the OnChanged partial method.
e.g.
public partial class Test
{
public int AB
{
get { return A * B; }
}
public partial void OnAChanged()
{
OnPropertyChanged("AB");
}
public partial void OnBChanged()
{
OnPropertyChanged("AB");
}
}
If there is an automatic way for this to work, I would like to know too.