A simple RequiredField validator really this complex? - validation

Using the INotifyDataErrorInfo I have validation methods in my setters of my properties, this works fine if I change the field value and then leave the control (change focus) the setter gets fired and validation occurs and the UI is notified, but using that interface, if the user just presses submit how can I do something similar to RequiredField like in asp.net, I can't seem to find a clear cut example on any forum or blog :(
I'm using Silverlight 4 WCF RIA and the mvvm-light toolkit, thats it. I hope im not over complexing this, because it seems like it should be so simple but can't seem to figure out a solution.
Thank you for all your help, suggestions and pointers!!!

Finally found a simple solution... Please let me know if anyone has a more efficient way of doing this :)
private void Validate()
{
ValidationContext validationContext = new ValidationContext(this, null, null);
ICollection vr = new List();
Validator.TryValidateObject(this, validationContext, vr, true);
if (vr.Count >= 1)
{
foreach (var item in vr)
{
ManageErrors(((string[])item.MemberNames)[0], new List() { item.ErrorMessage }, true);
}
}
}
The Manage Errors method is the simple implementation of the INotifyDataErrorInfo that Jesse Liberty did here
any ways now when my submit method gets called (using mvvm-light) in my viewModel i call this and bam all properties validated using simple dataAnnotations
ie
[Required(ErrorMessage = "Is Required", AllowEmptyStrings = false)]
public string SelectedStatus
{
get { return _selectedStatus; }
set
{
_selectedStatus = value;
RaisePropertyChanged("SelectedStatus");
}
}
Not the most elegant way of doing it but... by god I could not find anyone validating on a submit!?!?

Related

OnChange in MudBlazor RadioButtonGroup

I am new to Blazor and MudBlazor. I am using a and I want to call an event when the selection changes. The documentation show there is a EventCallback method but there are no syntax examples. I have been searching a good part of the day but cannot find an example. Can anyone please share some simple code? I know I can bind to a variable, and I initially did that. What I want is to call code and do some different code based on the selected value. Seems to be easier to do in Blazor syntax vs MudBlazor.
I appreciate any help.
Thank you
<MudRadioGroup T="string" SelectedOption="#SelectedOption" SelectedOptionChanged="OnSelectedOptionChanged">
<MudRadio Option="#("Radio 1")" Color="Color.Primary">Primary</MudRadio>
<MudRadio Option="#("Radio 2")" Color="Color.Secondary">Secondary</MudRadio>
<MudRadio Option="#("Radio 3")">Default</MudRadio>
<MudRadio Option="#("Radio 4")" Color="Color.Primary" Disabled="true">Disabled</MudRadio>
</MudRadioGroup>
#code {
public string SelectedOption { get; set; }
private void OnSelectedOptionChanged(string selectedOption)
{
SelectedOption = selectedOption;
// call your stuff
}
}
https://try.mudblazor.com/snippet/mOQGYtGKUpgnQxqe

Persistent Storage using Application.Current.Properties not working

I'm trying to achieve a persistent storage in Xamarin.Forms. After researching in Xamarin.Forms, I decided to use Application.Current.Properties property.
It looks like it is working just only if the app still remains alive. If I close the app and start it again the Application.Current.Properties is empty.
Does anyone know if I'm doing something wrong? Can I achieve this feature in another way?
As usual, thanks guys.
I have had a ton of problems with Application.Current.Properties on Android. I highly suggest using Xamarin Settings plugin instead which I have never had any issues with. It is persistent even when the app is closed.
That being said Application.Current.Properties is supposed to work even when you close the app. Not sure why it wouldn't but it does not surprise me either.
*Edit: To use once it is installed, basically CrossSettings.Current is the plugin class that will do the work but the example just creates a separate property to access it. So create a new file, lets call it SettingsImplementation:
public static class SettingsImplementation {
#region Instance
private static Lazy<ISettings> _appSettings;
public static ISettings AppSettings {
get {
if(_appSettings == null) {
_appSettings = new Lazy<ISettings>(() => CrossSettings.Current, LazyThreadSafetyMode.PublicationOnly);
}
return _appSettings.Value;
}
set {
_appSettings = new Lazy<ISettings>(() => value, LazyThreadSafetyMode.PublicationOnly);
}
}
#endregion
private const string UserNameKey = "username_key"; //Key used to get your property
private static readonly string UserNameDefault = string.Empty; //Default value for your property if the key-value pair has not been created yet
public static string UserName {
get { return AppSettings.GetValueOrDefault<string>(UserNameKey, UserNameDefault); }
set { AppSettings.AddOrUpdateValue<string>(UserNameKey, value); }
}
}
Then to use that you would do this anywhere in your app:
SettingsImplementation.UserName = "something";
OR
string username = SettingsImplementation.UserName;
My own problem regarding this issue was due to me not explicitly saving the properties with the following line of code:
Application.Current.SavePropertiesAsync();
you can use Xamarin essentials "Preferences" instead:
Preferences.Set("Key", "Value");
Preferences.Get("Key", "Default");
I ran into the same issue.
The problem:
I was trying to throw complex objects into the Application Properties.
It turns out that the Properties can only take primitive data typs.
This Blog was very helpfull.
https://codemilltech.com/persist-whatever-you-want-with-xamarin-forms/

How to pursuade the ApiExplorer to create documentation for ExpandoObject?

I've created a very neat way of implementing a PATCH method for my Web.API project by making use of an ExpandoObject as a parameter. As illustrated below:
[HttpPatch, Route("api/employee/{id:int}")]
public IHttpActionResult Update(int id, [FromBody] ExpandoObject employee)
{
var source = Repository.FindEmployeeById(id);
Patch(employee, source);
Repository.SaveEmployee(source);
return Ok(source);
}
However, when generating documentation ApiExplorer is at a loss as to what to do with the ExpandoObject, which is totally understandable. Would anyone have any ideas on how to manipulate the ApiExplorer to provide some sensible documentation?
My idea was to maybe introduce an new attribute which points to the actual Type that is expected:
public IHttpActionResult Update(int id, [FromBody, Mimics(typeof(Employee))] ExpandoObject employee)
{
...
}
But I have no idea where to start, any ideas or suggestions are welcome.
So this has been the source of some late evenings in order to get the Api Explorer to play along with our developed Http Patch mechanism. Truth be told, I'd probably should do a bit of a proper write up to full explain the mechanics behind the whole idea. But for those of you who landed on this page because you want the Api explorer to use a different type in the documentation, this is where you need to look:
Open HelpPageConfigurationExtensions.cs and locate the following method:
//File: Areas/HelpPage/HelpPageConfigurationExtensions.cs
private static void GenerateRequestModelDescription(HelpPageApiModel apiModel, ModelDescriptionGenerator modelGenerator, HelpPageSampleGenerator sampleGenerator)
{
....
}
this is the location where the parameter information is available to you and also provides you with the ability to replace/substitute parameter information with something else. I ended up doing the following to handle my ExpandoObject parameter issue:
if (apiParameter.Source == ApiParameterSource.FromBody)
{
Type parameterType = apiParameter.ParameterDescriptor.ParameterType;
// do something different when dealing with parameters
// of type ExpandObject.
if (parameterType == typeof(ExpandoObject))
{
// if a request-type-attribute is defined, assume the parameter
// is the supposed to mimic the type defined.
var requestTypeAttribute = apiParameter.ParameterDescriptor.GetCustomAttributes<RequestTypeAttribute>().FirstOrDefault();
if (requestTypeAttribute != null)
{
parameterType = requestTypeAttribute.RequestType;
}
}
}
Just, note that the RequestTypeAttribute is something I devised. My WebApi endpoint looks like this now:
public IHttpActionResult Update(int id,
[FromBody, RequestType(typeof(Employee))] ExpandoObject employee)
Thank you to everyone who took time to look into the problem.

Automatically detect when storing an object with ServiceStack.Redis

I am looking for a way to subscribe to events like Storing a specific object type to ServiceStack.Redis.
For example I may
using (var redisClient = new RedisClient())
using (var redisMyObjects = redisClient.As<MyObject>())
{
redisMyObjects.Store(myObject);//<-- I want this to trigger an event somehow
}
Is there anything like a OnStore event which I can hook too, anything out of the box? if not, is there any recommendation about how this should be done?
I don't think there is anything you can hook into (could be wrong).
Two options that came to mind:
1 - Make an extension method
2 - Publish a message to store your object and have a handler that listens for a response and does something. This is probably overkill since it's heading into the publish/subscribe realm. But, I think, worth looking into. (Basic example here and see Pub/Sub here).
Extension Method
public static class RedisClientExtensions
{
public static void StoreWithTrigger<T>(this IRedisTypedClient<T> redisClient, T value, Action<T> trigger)
{
redisClient.Store(value);
trigger(value);
}
}
Using ExtensionMethod
public void MyMethod()
{
using (var redisClient = new RedisClient())
using (var redisMyObjects = redisClient.As<MyObject>())
{
redisMyObjects.StoreWithTrigger<MyObject>(new MyObject(), TriggerEvent);//<-- I want this to trigger an event somehow
}
}
private void TriggerEvent<T>(T value)
{
//dosomething
}
Hope this gives you some ideas.

ViewModels and IsolatedStorageSettings

Im working on a MVVM Windows phone app that displays weather info.
When the app loads up it opens MainPage.xaml. It makes a call the the service to get weather info and binds that data to the UI. Both Fahrenheit and Celcius info are returned but only one is displayed.
On the setting page, the user can select to view the temp in either Fahrenheit or Celcius.
The user can change this setting at any time and its stored in IsolatedStorageSettings.
The issue Im having is this:
when the user navigates to the Settings page and changes their preference for either Fahrenheit or Celcius, this change is not reflected on the main page.
This issue started me thinking about this in a broader context. I can see this being an issue in ANY MVVM app where the display depends on some setting in IsolatedStorage. Any time any setting in the IsoStore is updated, how does the ViewModels know this? When I navigate back in the NavigationStack from the settings page back to MainPage how can I force a rebind of the page?
The data in my model hasnt changed, only the data that I want to display has changed.
Am I missing something simple here?
Thanks in advance.
Alex
Probably you have code like this:
public double DisplayTemperature
{
get { return (IsCelsium) ? Celsium : Fahrenheit; }
}
And IsCelsium is:
public double IsCelsium
{
get { return (bool)settings["IsCelsium"]; }
set { settings["IsCelsium"] = value; }
}
So you need to add NotifyPropertyChanged event to notify UI to get new values from DisplayTemperature property:
public double IsCelsium
{
get { return (bool)settings["IsCelsium"]; }
set
{
settings["IsCelsium"] = value;
NotifyPropertyChanged("DisplayTemperature");
}
}
Take a look at Caliburn Micro. You could implement something similar or use CM itself. When using CM I don't even think about this stuff, CM makes it so simple.
When your ViewModel inherits from Screen there are life-cycle events that fire that you can override. For example, OnInitialize fires the very first time the ViewModel is Activated and OnActivate fires every time the VM is activated. There's also OnViewAttached and OnViewLoaded.
These methods are the perfect place to put logic to populate or re-populate data.
CM also has some special built in features for allowing one to easily tombstone a single property or an entire object graph into Iso or phone state.
ok, so Ive come up with a solution. Before I get to it, let me provide some background. The app that Im working on uses both MVVM Light and WP7Contrib. That being the case, I am using Funq for DI and the MVVMLight Toolkit. After I posted my initial question, I gave the question a bit more thought. I remembered a video that I watched a while back from MIX2011 called Deep Dive MVVM with Laurent Bugnion
http://channel9.msdn.com/Events/MIX/MIX11/OPN03
In it, he talks about just this problem (view models not living at the same time) on Windows Phone. The part in question starts around the 19 minute mark.
Anyway, after I remembered that and realized that the ViewModel locator is exposed in App.xaml, this became a trivial problem to solve. When the user changes the Fahrenheit/Celcius option on the setting page, I simply get a reference to the MainViewModel via the ViewModelLocator and reset the collection that is bound to the UI thus causing the bindings to update.
public bool AddOrUpdateValue(string Key, Object value)
{
bool valueChanged = false;
// If the key exists
if (settings.Contains(Key))
{
// If the value has changed
if (settings[Key] != value)
{
// Store the new value
settings[Key] = value;
valueChanged = true;
}
}
// Otherwise create the key.
else
{
settings.Add(Key, value);
valueChanged = true;
}
return valueChanged;
}
public bool ImperialSetting
{
get
{
return GetValueOrDefault<bool>(ImperialSettingKeyName, ImperialSettingDefault);
}
set
{
if (AddOrUpdateValue(ImperialSettingKeyName, value))
{
Save();
RaisePropertyChanged("ImperialSettingText");
var vml = new ViewModelLocator();
vml.MainViewModel.Cities = (App.Current as App).Cities;
}
}
}
It was a mistake on my part not to realize that I could get access to the viewModel via the ViewModelLocator. Hopefully this post saves someone else the time I burned on this issue.

Resources