I apologize in advance if my question is a bit vague.
I am looking into and learning reactiveui which I find a very interesting concept. For that, I am building a small application using WPF and Prism and I am having some difficulties understanding the way commands are build in the View Models.
I have an example which, if complete, will hopefully clarify things for me a little bit:
I would like to have a grid that displays some data. This data is loaded from a web service and my goal is to load it once when the view is shown to the user and then to reload it every x times (once a minute, for example) or when explicitly triggered from a button in the View.
So, my View Model currently looks like:
public class MyPageViewModel : ReactiveValidatedObject
{
/// <summary>
/// Collection of tickets
/// </summary>
public ReactiveCollection<TicketModel> Tickets { get { return _Tickets.Value; } }
/// <summary>
/// Private store of tickets
/// </summary>
private ObservableAsPropertyHelper<ReactiveCollection<TicketModel>> _Tickets { get; set; }
/// <summary>
/// The service which retrieves the tickets
/// </summary>
private ITicketService _ticketService;
public MyPageViewModel() : this(null) { }
public MyPageViewModel(ITicketService ticketService)
{
LoadTickets = new ReactiveAsyncCommand(null, 0);
}
/// <summary>
/// A command which exposes the load action for the tickets
/// </summary>
public ReactiveAsyncCommand LoadTickets { get; private set; }
private void loadTickets()
{
//returns a List<TicketModel>
var tickets = _ticketService.GetTickets();
}
}
My questions are:
1) How do I register an async command which will be fired every x times and will call the internal loadTickets function that will reload the Ticket storage? This command will also be fired by the exposed command LoadTickets.
2) In the function, loadTickets I will fetch each time a List from the service. How do I convert this list to the ReactiveCollection that is exposed to the UI.
1) How do I register an async command which will be fired every x times and will call the internal loadTickets function that will reload the Ticket storage? This command will also be fired by the exposed command LoadTickets.
Observable.Timer(TimeSpan.FromSeconds(10), RxApp.DeferredScheduler)
.InvokeCommand(LoadTickets);
2) In the function, loadTickets I will fetch each time a List from the service. How do I convert this list to the ReactiveCollection that is exposed to the UI.
// This makes it so when you invoke LoadTickets.Execute, Tickets
// gets updated.
// NB: Make loadTickets return a List<Ticket>
LoadTickets.RegisterAsyncFunc(x => loadTickets())
.Select(x => new ReactiveCollection<Ticket>(x))
.ToProperty(this, x => x.Tickets);
Related
DbSet<T>.Local provides an ObservableCollection that you can bind to WPF controls. In my case, I'm binding it to a grid.
If I was using view models, I would have them implement INotifyDataErrorInfo or IDataErrorInfo, and then write Fluent Validation validators to handle validation.
But here I'm binding to the models via DbSet<T>.Local. How should I handle validation?
Should I implement INotifyDataErrorInfo or IDataErrorInfo on my models?
Or is there some alternative?
If you are application is a thick client, meaning all layers of the application are on a single physical machine, then you should implement IDataErrorInfo on your models.
On the other hand, if your application is a thin multi-tired application, meaning that your model is implemented on a server and you are using the WPF desktop application to communicate with the server side code then you should implement INotifyDataErrorInfo.
Yes I think implement implementing IValidatableObject in POCO Models makes sense.
And you have probably noticed public ObservableCollection<TEntity> Local { get; }
There are several ways to do this. So a some homework.
As some background , might be useful
Then check this out
So we know EF has the concept of triggering Validations.
Configuration.ValidateOnSaveEnabled = true;
EF will also call IEnumerable<ValidationResult> ValidateInstance();
from interface IValidatableObject
if your entity POCO implements IValidatableObject
EF will trigger validate on SAve.
You can also easily trigger validations when you need to.
This all neatly links in with UoW concept.
public IEnumerable<DbEntityValidationResult> GetDbValidationErrors() { return
Context.GetValidationErrors(); } // Standard Context call get the problems
which can be used
catch (Exception ex) {....
var x = GetDbValidationErrors();
//....
So i think you are on the right track...
EDIT: Add SAMPLE POCOBase and demonstrate trigger validation.
public interface IFBaseObject : IValidatableObject {
// a POCO object must implement the VALIDATE method from IValidatableObject
bool IsValidInstance();
IEnumerable<ValidationResult> ValidateInstance();
}
public abstract class BaseObject : IFBaseObject {
// .... base object stuff removed....
/// <summary>
/// Get called every a Validation is trigger on an object. Here we return and Empty resultset to start with.
/// If you override ALWAYS call Base first and Continue to add your own results as desired.
/// Never fail to call base First !
/// </summary>
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
# region Sample implementation for a POCO thats needs validation
/* Sample Implementation a sub type POCO might use.
var validationResult = base.Validate(validationContext).ToList();
if (true) // the condition that leads to a validation error
{
var memberList = new List<string> { "PropertyName" }; // the name of the offending property
var error = new ValidationResult("Error text goes here", memberList); // use teh textpool !!! no hardcoded texts
validationResult.Add(error);
}
return validationResult;
*/
# endregion
// now back in the base Class.
var validationResult = new List<ValidationResult>();
// hand back a list that is empty so errors if any can be added by SUBclasses
// we can check any Poco that implements a certain interface centrally.
var thisIsKeyGuid = this as IFKeyGuid;
if (thisIsKeyGuid != null) {
if (thisIsKeyGuid.Id == Guid.Empty) {
validationResult.Add(new ValidationResult("Id is required", new List<string>() {"Id"}));
}
}
return validationResult;
}
/// <summary>
/// Allows explicit triggering of Validation and returns a TRUE or false answer. Call anytime
/// </summary>
/// <returns></returns>
public virtual bool IsValidInstance() {
List<ValidationResult> vResults;
return SelfValidation(out vResults);
}
/// <summary>
/// Calls Self Validation which uses THIS object as the context for validation.
/// This means you can trigger a validation without first declaring a validation context.
/// IValidatableObject is effectively called for you. Witch causes "Validate" to be called
/// </summary>
/// <returns></returns>
public IEnumerable<ValidationResult> ValidateInstance() {
List<ValidationResult> vResults;
SelfValidation(out vResults);
return vResults;
}
/// <summary>
/// Although SelfValidation is defined at BaseObject level, this triggers the VALIDATION process on the current Object
/// see http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validator.aspx for mroe details
/// So if a POCO Object has overridden public virtual IEnumerable of ValidationResult Validate(ValidationContext validationContext)
/// then this method will be called. It should of course call :base.Validate
/// </summary>
/// <returns>true or false</returns>
private bool SelfValidation(out List<ValidationResult> vResults) {
var vc = new ValidationContext(this, null, null);
vResults = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(this, vc, vResults, true);
return isValid;
}
}
I'm moving to using the SimpleIoc for Dependency Injection from using a Static class. There is a Register<TClass>(Func<TClass> factory) where TClass : class method in the SimpleIoc, but I can't find any examples of using it. Here's a link to the source code.
Am I approaching this correctly, or does DI always need to create it at register time? Is this the method I should use to register the class? Can you give me an example on how to do this?
This is the Silverlight code I'm trying to update.
EDIT: moved my approach to an answer
I moved my example from my question to an answer, since no one else has answered it in 22 days. EDIT: this is better.
public partial class App : Application
{
/// <summary>
/// Initializes a new instance of the <see cref="App"/> class.
/// </summary>
public App()
{
this.Startup += (s, e) =>
{
// create and register it now
SimpleIoc.Default.Register<IUserToken>(() => { return new UserToken(); });
SimpleIoc.Default.GetInstance<IUserToken>().PopulateUserTokenFromService(() =>
{
// don't do anything until the user token is populated from the server
InitializeComponent();
this.RootVisual = new View();
});
}
}
I have a WCF Data Service in my web app. I added a service reference using the "Add New Service Reference" command in my Silverlight application. I was looking at the Reference.cs file VS generates for me and noticed the setters don't check for a change before calling OnPropertyChanged. I'd like to change this behavior. Can I overrride the T4 template without having to override all the code generation?
If it's possible how would I go about doing it?
original generated code
/// <summary>
/// There are no comments for Property Title in the schema.
/// </summary>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Services.Design", "1.0.0")]
public string Title
{
get
{
return this._Title;
}
set
{
this.OnTitleChanging(value);
this._Title = value;
this.OnTitleChanged();
this.OnPropertyChanged("Title");
}
}
Desired change:
/// <summary>
/// There are no comments for Property Title in the schema.
/// </summary>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Services.Design", "1.0.0")]
public string Title
{
get
{
return this._Title;
}
set
{
// change to
if(this._Title != value) {
this.OnTitleChanging(value);
this._Title = value;
this.OnTitleChanged();
this.OnPropertyChanged("Title");
}
}
}
Unfortunately the Add Service Reference for WCF Data Services doesn't use T4 yet. So there's no easy way to do this. Feel free to vote for the feature here: http://blogs.msdn.com/b/astoriateam/archive/2010/09/10/what-do-you-want-to-see-added-changed-in-wcf-data-services.aspx
ok, I know this is asked a million times, but I still can't seem to find a working solution. Hopefully I'm just missing something.
Using entity with silverlight, through RIA
I have a many to many table structure in my DB.
[System] - [SystemUsers] - [Users]
The bridge table just has the two IDs so naturaly entity doens't include it in the model.
I know RIA doesn't like many to many relationships, so I've added Association attribute tags to the collection, and can now at least see the collection property on the client side.
[Association("DMSSystem_Users", "DMSSystemId", "UserId")]
[Include]
[Composition]
public EntityCollection<Users> Users { get; set; }
In my domain service I've tried including the users:
public IQueryable<DMSSystem> GetSystem()
{
return this.ObjectContext.DMSSystem.Include("Users");
}
I never get the users on the client side Is there something else I am missing to get the users to be inculded and sent to the client?
RIA with EF has a dislike for M:M relationships. What you need to do is to help RIA see the M:M as two 1:M relationships.
On your link table add an extra column (I add something like IgnoreThisField) and make it a bit type.
When EF sees this table it will now interpret it differently allowing you to handle the M:M relationship.
I don't know Entity Framework but here's how this works in RIA with NHibernate...
My model is Users - UserRoleGrant - Role. You'll have to do the translation to your model in your head.
The important parts of the following code are... ensure you have the correct association names on your model, ensure you have the correct property names set in your associations, set the UserID property on the UserRoleAssociation when you set it's User property. If you don't set this ID you wont have access to the related entity via the assocation property.
You probably don't need the Composition attribute either but you might so read this to find out... http://ria.feedables.com/story/4583193/Composition-Support-in-RIA-Services
public class User
{
...snip...
[Include]
[Association("UserToRoleAssociation", "Id", "UserId", IsForeignKey = false)]
public virtual IList<UserRoleAssociation> RoleGrants
{
get
{
return this.roleGrants;
}
}
}
public class UserRoleAssociation
{
/// <summary>
/// Backing field for User
/// </summary>
private User user;
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>The relationships id.</value>
[Key]
public virtual long Id { get; set; }
/// <summary>
/// Gets or sets the user id.
/// </summary>
/// <value>The assigned users id.</value>
public virtual long UserId { get; set; }
/// <summary>
/// Gets or sets the user.
/// [Association("UserRoleGrants", "UserId", "Id", IsForeignKey = false)]
/// </summary>
/// <value>The user who has been granted this operation.</value>
[Include]
[Association("UserToRoleAssociation", "UserId", "Id", IsForeignKey = true)]
public virtual User User
{
get
{
return this.user;
}
set
{
this.user = value;
if (value != null)
{
this.UserId = value.Id;
}
}
}
}
Just ran across this: http://m2m4ria.codeplex.com/
It requires some setup, but exposes a view to the client which solves the whole many-to-many issue, without modifying your database or entity model. I found it very useful.
I want to access the Title value that is stored in the WMAppManifest.xml file from my ViewModel code. This is the same application title that is set through the project properties.
Is there a way to access this from code using something like App.Current?
Look at the source code for WP7DataCollector.GetAppAttribute() in the Microsoft Silverlight Analytics Framework. GetAppAttribute("Title") will do it.
/// <summary>
/// Gets an attribute from the Windows Phone App Manifest App element
/// </summary>
/// <param name="attributeName">the attribute name</param>
/// <returns>the attribute value</returns>
private static string GetAppAttribute(string attributeName)
{
string appManifestName = "WMAppManifest.xml";
string appNodeName = "App";
var settings = new XmlReaderSettings();
settings.XmlResolver = new XmlXapResolver();
using (XmlReader rdr = XmlReader.Create(appManifestName, settings))
{
rdr.ReadToDescendant(appNodeName);
if (!rdr.IsStartElement())
{
throw new System.FormatException(appManifestName + " is missing " + appNodeName);
}
return rdr.GetAttribute(attributeName);
}
}
This last answer seems overly complicated to me ; you could have simply done something like:
string name = "";
var executingAssembly = System.Reflection.Assembly.GetExecutingAssembly();
var customAttributes = executingAssembly.GetCustomAttributes(typeof(System.Reflection.AssemblyTitleAttribute), false);
if (customAttributes != null)
{
var assemblyName = customAttributes[0] as System.Reflection.AssemblyTitleAttribute;
name = assemblyName.Title;
}
I have used Michael S. Scherotter his excellent code sample to work it out to a fully working code sample:
using System.Xml;
namespace KoenZomers.WinPhone.Samples
{
/// <summary>
/// Allows application information to be retrieved
/// </summary>
public static class ApplicationInfo
{
#region Constants
/// <summary>
/// Filename of the application manifest contained within the XAP file
/// </summary>
private const string AppManifestName = "WMAppManifest.xml";
/// <summary>
/// Name of the XML element containing the application information
/// </summary>
private const string AppNodeName = "App";
#endregion
#region Properties
/// <summary>
/// Gets the application title
/// </summary>
public static string Title
{
get { return GetAppAttribute("Title"); }
}
/// <summary>
/// Gets the application description
/// </summary>
public static string Description
{
get { return GetAppAttribute("Description"); }
}
/// <summary>
/// Gets the application version
/// </summary>
public static string Version
{
get { return GetAppAttribute("Version"); }
}
/// <summary>
/// Gets the application publisher
/// </summary>
public static string Publisher
{
get { return GetAppAttribute("Publisher"); }
}
/// <summary>
/// Gets the application author
/// </summary>
public static string Author
{
get { return GetAppAttribute("Author"); }
}
#endregion
#region Methods
/// <summary>
/// Gets an attribute from the Windows Phone App Manifest App element
/// </summary>
/// <param name="attributeName">the attribute name</param>
/// <returns>the attribute value</returns>
private static string GetAppAttribute(string attributeName)
{
var settings = new XmlReaderSettings {XmlResolver = new XmlXapResolver()};
using (var rdr = XmlReader.Create(AppManifestName, settings))
{
rdr.ReadToDescendant(AppNodeName);
// Return the value of the requested XML attribute if found or NULL if the XML element with the application information was not found in the application manifest
return !rdr.IsStartElement() ? null : rdr.GetAttribute(attributeName);
}
}
#endregion
}
}
Only the first two answers are correct in scope of the original question. And the second is certainly not over complicated. Wrapping the helper method with a class for each possible attribute is good object orientated development and exactly what Microsoft do all over the framework, e.g. settings designer files generated by Visual Studio.
I'd recommend using the first if you just want one specific property, the second if you want more. Should be part of the SDK really. We're trying to read the WMAppManifest.xml here not the AssemblyInfo so standard assembly reflection metadata is no good.
By the way, if you really want to get the product name from the assembly attributes (not WPAppManifest.xml) then the last sample was reading the wrong attribute! Use the AssemblyProductAttribute not the AssemblyTitleAttribute. The assembly title is really the file title, by default the same as the assembly file name (e.g. MyCompany.MyProduct.WinPhone7App) whereas the product will typically be something like the properly formatted "title" of your app in the store (e.g. "My Product"). It may not even be up-to-date after using the VS properties page, so you should check that.
I use AssemblyInfo reflection for all other application types to show the official product name and build version on an about page, it's certainly correct for that. But for these special phone app types the store manifest has more importance and other attributes you may need.
The problem with all of those answers is that they have to read the file every single time it is accessed. This is bad for performance as there are battery issues to consider if you use it frequently. Koen was closer to a proper solution, but his design still went back to the file every time you wanted to access the value.
The solution below is a one-and-done read of the file. Since it is not likely to change, there is no reason to keep going back to it. The attributes are read as the static class is initialized, with minimal fuss.
I created this Gist to demonstrate.
HTH!