Silverlight ValidationSummary not handling ValidationException - validation

I have a dataform and a datagrid in the dataform. this datagrid is bound to an ObservableCollection. I have written a CustomValidator that throws ValidationException when the count in the observable collection is 0. ValidationSummary control doesn't handle this exception, instead the application becomes unstable and calls Application Unhandled Exception. I am not using RIA services. Below is my code
public class UserCompanyProgram : INotifyPropertyChanged
{
public void ToWebServiceProgram()
{
lstUserProgram.CollectionChanged += (sender, e) =>
{
//Validator.ValidateProperty(lstUserProgram,
// new ValidationContext(this, null, null) { MemberName = "lstUserProgram" });
lstUserProgram = _lstUserProgram;
UserProgramChanged();
};
}
private ObservableCollection<Pricing.Model.UserProgram> _lstUserProgram = new ObservableCollection<UserProgram>();
[CustomValidation(typeof(ModelValidator), "ValidateUserProgramCollection")]
[Display(Name = "New Programs", Description = "Add program")]
public ObservableCollection<UserProgram> lstUserProgram
{
get { return _lstUserProgram; }
set
{
Validator.ValidateProperty(lstUserProgram,
new ValidationContext(this, null, null) { MemberName = "lstUserProgram" });
this._lstUserProgram = value;
NotifyPropertyChanged("lstUserProgram");
}
}
}
dgSelectedPrograms.SetBinding(DataGrid.ItemsSourceProperty, new Binding("lstUserProgram") { ValidatesOnNotifyDataErrors=true, ValidatesOnExceptions=true });
How do I make the ValidationSummary handle the exception?

I had a similar issue in my project where I was forcing the validation on the keyup event of the textbox. I was setting the textbox bound property to the text from the textbox, on the keyup event, so I could validate as they typed. Silverlight does not like this. It was throwing an unhandled exception. So once I removed the validation from the keyup event, it worked as it should. The property does not get updated until the user selects another control on the screen, but if I want to take advantage of the Silverlight validation, that's what needs to be done.
I have not worked with validating a collection such as what you're doing, but maybe in cases like that you need to use the IDataErrorInfo implementation. An exception doesn't get thrown in that case, so that is probably the way to go.

Related

How to get Label view in ViewModel to set accessibility focus in xamarin forms

I have Label in view, I need that Label's view in my ViewModel. I am using Dependency Service to set focus on Controls for Accessibility service, DS requires view as a param.
This is my Label
<Label
AutomationProperties.IsInAccessibleTree="{Binding ShowNoResults}"
IsVisible="{Binding ShowNoResults}"
Text="{Binding ResultsHeader}"/>
I tried Command but Label doesn't support command. Below code also not working
var view = GetView() as HomeworkView;
I am getting view always null. How can I fix this?
I am not quite sure what are you trying to achieve, but you can't access the View elements from you view model.
If you want to do something with the control, you can use the messaging center to do it, here is an example
in your ViewModel
MessagingCenter.Send(this, "your message here");
then in your page, you need to subscribe to this message from that view model and do the desired action
MessagingCenter.Instance.Unsubscribe<ViewModelClassNamedel>(this, "your message here");
MessagingCenter.Instance.Subscribe<ViewModelClassName>(this, "your message here", (data) =>
{
this.youControlName.Focus();
});
More detail added to Mohammad's answer.
Message Center doc.
In your ViewModel (with class name "YourViewModel"):
// Here we use control name directly.
// OR could make an "enum" with a value for each control.
string controlName = ...;
MessagingCenter.Send<YourViewModel>(this, "focus", controlName);
then in your page, subscribe to this message and do the desired action
.xaml.cs:
protected override void OnAppearing() {
{
base.OnAppearing();
// Unsubscribe before Subscribe ensures you don't Subscribe twice, if the page is shown again.
MessagingCenter.Instance.Unsubscribe<YourViewModel>(this, "focus");
MessagingCenter.Instance.Subscribe<YourViewModel>(this, "focus", (controlName) =>
{
View v = null;
switch (controlName) {
case "name1":
v = this.name1;
break;
case "name2":
v = this.name2;
break;
}
if (v != null) {
//v.Focus();
// Tell VM to use v as view.
((YourViewModel)BindingContext).SetFocus(v);
}
});
}
protected override void OnDisappearing() {
MessagingCenter.Instance.Unsubscribe<YourViewModel>(this, "focus");
base.OnDisappearing();
}
If need to pass View v back to VM, because that has the logic to use it:
public class YourViewModel
{
public void SetFocus(View view)
{
... your code that needs label's view ...
}
}
Not tested. Might need some slight changes. Might need
...(this, "focus", (sender, controlName) =>
instead of
...(this, "focus", (controlName) =>
UPDATE
Simple approach, if there is only ONE View that is needed in VM.
public class YourViewModel
{
public View ViewToFocus { get; set; }
// The method that needs ViewToFocus.
void SomeMethod()
{
...
if (ViewToFocus != null)
... do something with it ...
}
}
public class YourView
{
public YourView()
{
InitializeComponent();
...
// After BindingContext is set.
((YourViewModel)BindingContext).ViewToFocus = this.yourLabelThatShouldBeFocused;
}
}
ALTERNATIVE: It might be cleaner/more robust to set ViewToFocus in page's OnAppearing, and clear it in OnDisappearing. This ensures it is never used while the page is not visible (or in some delayed action after the page has gone away). I would probably do it this way.
protected override void OnAppearing()
{
base.OnAppearing();
((YourViewModel)BindingContext).ViewToFocus = this.yourLabelThatShouldBeFocused;
}
protected override void OnDisappearing()
{
((YourViewModel)BindingContext).ViewToFocus = null;
base.OnDisappearing();
}

Vibe.d basic form validation

I have a post create method:
void gönderiyiOluştur(HTTPServerRequest istek, HTTPServerResponse yanıt)
{
render!("gönderiler/oluştur.dt")(yanıt);
}
and a post store method like this:
void gönderiyiKaydet(HTTPServerRequest istek, HTTPServerResponse yanıt)
{
auto başlık = istek.form["baslik"];
auto içerik = istek.form["icerik"];
bool yayınla = false;
if (başlık.length > 0)
{
Gönderi gönderi = Gönderi(başlık, içerik);
gönderi.kaydet();
yanıt.redirect("/");
}
else
{
yanıt.redirect("/gönderiler/oluştur");
}
}
I'd like to make basic form validation. For example if input fields are empty it redirects to previous page.
I suppose I should pass some error message to the create method like baslik field should not be empty etc..
But since I am quite new to framework I shouldn't figure out. Are there any facilities does the framework offer for form validation.
Basic form validation is easy when you use the web framework from vibe.d. The basic steps are:
Create a class Gönderiyi and put your kaydet method inside this class:
class Shipment {
#method(HTTPMethod.POST)
void kaydet() { ... }
}
Define a method inside the class which should be called in case a validations fails. This method should display the error message:
void getError(string _error = null, HTTPServerResponse res) { ... }
Annotate the kaydet method with the #errorDisplay attribute to connect the method with the error function:
class Shipment {
#method(HTTPMethod.POST)
#errorDisplay!getError
void kaydet() { ... }
void getError(string _error = null, HTTPServerResponse res) { ... }
}
Now do the validation inside the kaydet method and throw an exception in case of an error. The getError method is then called automatically. You can take advantage of parameter binding and conversion, too. When the D parameter name is the same as the name of an HTML input value, then this value is bind to the D parameter. Automatic type conversion takes place (e.g. to int) and can lead to exceptions, which are then handled in the getError method, too.
As last step you need to register your class with the web framework:
auto router = new URLRouter;
router.registerWebInterface(new Gönderiyi);
You should have a look at the documentation of errorDisplay and at the web framework example from vibe.d, too.

Stop validation error item from being published

We are using Sitecore 7.2 and have implemented the 'Required' field validator for number of fields.
However, the user can still save or create an item with validation error.
I know that we can stop this validation errored items from being published using Work Flow.
We do not want to implement any workflow, therefore can someone please suggest how to stop validation errored item from being able to published?
You can create your own validation class like this (the one below only check for validation bar errors):
public void ValidateItem(object sender, EventArgs args)
{
ItemProcessingEventArgs theArgs = (ItemProcessingEventArgs) args;
Item currentItem = theArgs.Context.PublishHelper.GetSourceItem(theArgs.Context.ItemId);
if ((currentItem != null) && (currentItem.Paths.IsContentItem))
{
if (!IsItemValid(currentItem))
{
theArgs.Cancel = true;
}
}
}
private static bool IsItemValid(Item item)
{
item.Fields.ReadAll();
ValidatorCollection validators = ValidatorManager.GetFieldsValidators(
ValidatorsMode.ValidatorBar, item.Fields.Select(f => new FieldDescriptor(item, f.Name)), item.Database);
var options = new ValidatorOptions(true);
ValidatorManager.Validate(validators, options);
foreach (BaseValidator validator in validators)
{
if (validator.Result != ValidatorResult.Valid)
{
return false;
}
}
return true;
}
and add event handler to publish:itemProcessing event:
<event name="publish:itemProcessing" help="Receives an argument of type ItemProcessingEventArgs (namespace: Sitecore.Publishing.Pipelines.PublishItem)">
<handler type="My.Assembly.Namespace.ValidateBeforePublish, My.Assembly" method="ValidateItem"/>
</event>
You could set the parameters field on the validation to "Result=FatalError" to stop the user from saving an item before the issue is resolved. This way the user has to fix the issue before they are allowed to save.

Checking to see if ViewBag has a property or not, to conditionally inject JavaScript

Consider this simple controller:
Porduct product = new Product(){
// Creating a product object;
};
try
{
productManager.SaveProduct(product);
return RedirectToAction("List");
}
catch (Exception ex)
{
ViewBag.ErrorMessage = ex.Message;
return View("Create", product);
}
Now, in my Create view, I want to check ViewBag object, to see if it has Error property or not. If it has the error property, I need to inject some JavaScript into the page, to show the error message to my user.
I created an extension method to check this:
public static bool Has (this object obj, string propertyName)
{
Type type = obj.GetType();
return type.GetProperty(propertyName) != null;
}
Then, in the Create view, I wrote this line of code:
#if (ViewBag.Has("Error"))
{
// Injecting JavaScript here
}
However, I get this error:
Cannot perform runtime binding on a null reference
Any idea?
#if (ViewBag.Error!=null)
{
// Injecting JavaScript here
}
Your code doesnt work because ViewBag is a dynamic object not a 'real' type.
the following code should work:
public static bool Has (this object obj, string propertyName)
{
var dynamic = obj as DynamicObject;
if(dynamic == null) return false;
return dynamic.GetDynamicMemberNames().Contains(propertyName);
}
Instead of using the ViewBag, use ViewData so you can check for the of the item you are storing. The ViewData object is used as Dictionary of objects that you can reference by key, it is not a dynamic as the ViewBag.
// Set the [ViewData][1] in the controller
ViewData["hideSearchForm"] = true;
// Use the condition in the view
if(Convert.ToBoolean(ViewData["hideSearchForm"])
hideSearchForm();
I would avoid ViewBag here completely.
See my thoughts here on this:
http://completedevelopment.blogspot.com/2011/12/stop-using-viewbag-in-most-places.html
The alternative would be to throw a custom error and catch it. how do you know if the database is down, or if its a business logic save error? in the example above you just catch a single exception, generally there is a better way to catch each exception type, and then a general exception handler for the truly unhandled exceptions such as the built in custom error pages or using ELMAH.
So above, I would instead
ModelState.AddModelError()
You can then look at these errors (assuming you arent jsut going to use the built in validation) via
How do I access the ModelState from within my View (aspx page)?
So please carefully consider displaying a message when you catch 'any' exception.
You can use ViewData.ContainsKey("yourkey").
In controller:
ViewBag.IsExist = true;
In view:
if(ViewData.ContainsKey("IsExist")) {...}
I need to test this but:
#if (ViewBag.ABoolParam ?? false)
{
//do stuff
}
I think will give you either the value of the ViewBag property, or return a default value if missing.

mvvmlight - what's the "proper way" of picking up url parameters for a view model

I'm just switching a project across to mvvmlight and trying to do things "the right way"
I've got a simple app with a listbox
When an item is selected in the listbox, then I've hooked up a RelayCommand
This RelayCommand causes a call on an INavigationService (http://geekswithblogs.net/lbugnion/archive/2011/01/06/navigation-in-a-wp7-application-with-mvvm-light.aspx) which navigates to a url like "/DetailPage.xaml?DetailId=12"
The DetailPage.xaml is then loaded and ... this is where I'm a bit unsure...
how should the DetailPage get hooked up to a DetailView with DetailId of 12?
should I do this in Xaml somehow using a property on the ViewLocator?
should I do this in the NavigatedTo method?
Please feel free to point me to a full sample - sure this has been done a (hundred) thousand times before, but all the blogs and tutorials seem to be skipping this last trivial detail (focussing instead on the messaging and on the ioc on on the navigationservice)
Thanks!
The only place you can retrieve the URL parameter is in the view. So since your view is likely depending on it, you should fetch it in the OnNavigatedTo method.
Then, you should pass it along to your viewmodel, either using messaging (to expensive if you ask me), or by referring to your datacontext (which is the viewmodel I presume), and execeuting a method on that.
private AddTilePageViewModel ViewModel
{
get
{
return DataContext as AddTilePageViewModel;
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var postalCode = NavigationContext.TryGetKey("PostalCode");
var country = NavigationContext.TryGetStringKey("Country");
if (postalCode.HasValue && string.IsNullOrEmpty(country) == false)
{
ViewModel.LoadCity(postalCode.Value, country);
}
base.OnNavigatedTo(e);
}
I'm using some special extensions for the NavigationContext to make it easier.
namespace System.Windows.Navigation
{
public static class NavigationExtensions
{
public static int? TryGetKey(this NavigationContext source, string key)
{
if (source.QueryString.ContainsKey(key))
{
string value = source.QueryString[key];
int result = 0;
if (int.TryParse(value, out result))
{
return result;
}
}
return null;
}
public static string TryGetStringKey(this NavigationContext source, string key)
{
if (source.QueryString.ContainsKey(key))
{
return source.QueryString[key];
}
return null;
}
}
}
Create a new WindowsPhoneDataBound application, it has an example of how to handle navigation between views. Basically you handle the navigation part in your view, then set the view's DataContext accord to the query string. I think it plays nicely with the MVVM pattern since your ViewModels don't have to know anything about navigation (which IMO should be handled at the UI level).

Resources