Select to view content in your preferred language

Editing FeatureLayer and Validation

1821
7
02-16-2011 06:24 AM
WilliamKimrey
Emerging Contributor
Hello all,

I've got a Silverlight 4 app that allows a user to edit one of 10 different Featurelayers withing the same FeatureService.  Basically, the user selects which layer to edit from a ComboBox.  I use that information to set up my Editor and a FeatureDataForm.  The user can add, remove, or edit these features, but what I want is Validation.

Currently, there are non-nullable fields and default values on some of the fields on the FeatureLayers, but each one has a different set of fields.  What I want to happen is a validation error when a user does not enter a value for a non-nullable field.

So I have 2 questsions here.  1) How to implement validation on a featuredataform and 2) How to make validation dynamic for the different featurelayers.

Thanks in advance,
Will
0 Kudos
7 Replies
JenniferNery
Esri Regular Contributor
FeatureDataForm and FeatureLayer performs validation based on the requirements of the feature service. Validation against type, domain and length.

If you need custom validation, you will need to write your own FeatureDataForm to ensure that certain fields are required and does not accept null values.

The source code for Toolkit is available in CodePlex http://esrisilverlight.codeplex.com/. If you need to take a look at what FeatureDataForm is currently doing.
0 Kudos
WilliamKimrey
Emerging Contributor
Thanks for the reply.  Sadly, I'm not able to make my own FeatureDataForm at this time.  As I said, I have about 10 different feature layers that I'm editing and I don't want to have to make a different form for each one.  Especially since the required fields for each feature layer are different.

I think I can get around this issue if there is a way to determine which fields are not nullable.  Most of my feature layers contain domains and have a default values, but one field in particular does not and it's this field that is causing the problem.  It has a domain, but not a default value so when the feature service tries to add a feature, it fails because this field has a null value and the featureclass itself does not allow nulls for this field.

This field that is causing a problem is not present in every feature class and some feature classes have different fields that cause the same problem.  So, if there's a way I can find out which fields do not allow nulls, I can check to see if they are null or not when I save and cancel the save if they are null.  I have yet to find a way to check for non nullable fields on a featurelayer.  Any ideas/suggestions?

Thanks again,
Will
0 Kudos
JenniferNery
Esri Regular Contributor
You can have a lookup dictionary that holds a list of non-nullable fields per layer.

Dictionary<string, List<Field>> lookup = new Dictionary<string, List<Field>>();

For each layer's Initialized event:
FeatureLayer l = sender as FeatureLayer
var nonNullableFields = new List<Field>();
foreach (var f in l.LayerInfo.Fields)
{
 if (!f.Nullable)
 nonNullableFields.Add(f);
}
lookup.Add(l.LayerInfo.Name, nonNullableFields);


If your FeatureLayer's AutoSave is False, you can explicitly call SaveEdits() in FeatureDataForm's EditEnded. This should allow you to perform validation check before saving the edits.
void f_EditEnded(object sender, EventArgs e)
{
 FeatureDataForm f = sender as FeatureDataForm;
 FeatureLayer l = f.FeatureLayer;
 Graphic g = f.GraphicSource;
 var nonNullableFields = lookup[l.LayerInfo.Name];
 foreach (var item in g.Attributes)
 {
  if (ContainsField(item.Key, nonNullableFields) && item.Value == null)
   throw new Exception(string.Format("Field '{0}' cannot be null", item.Key));
 }
 l.SaveEdits();
}

private bool ContainsField(string name, List<Field> fields)
{
 foreach (var f in fields)
  if (name == f.Name) return true;
 return false;
}
0 Kudos
WilliamKimrey
Emerging Contributor
Jennifer,

Thanks for the code.  My feature layer's AutoSave is set to false so i was checking at the EndSaveEdits event, but I hadn't figured out the initialization part of it yet.

I tested this code out and I'm sorry to say that it doesn't work.  I should work, but it's not returning a list of nonnullable fields.  I know for a fact that there area at least 5 nonnullable fields in one of my feature layers, but this code didn't catch any of them.

I'm starting to think it's something wrong with the FeatureService itself.  The features are inside of a versioned (without move to base) dataset on an 9.3.1 sde database.   However, the MXD was created in ArcDesktop 10 and published with ArcServer 10.  The application itself is Silverlight 4 using .NET Framework 4.  When you look at the fields in ArcDesktop, you see that they don't allow null values, so I can only conclude that something gets lost when I publish the service.  Any ideas?

Thanks again,
Will

Thanks,
Will
0 Kudos
AliMirzabeigi
Emerging Contributor
Since you are dealing with multiple feature layers, I would advise that you set default values at the SDE level, i.e. for the required CodedValueDomain attributes associate a default value, say empty string as Code.
Fields at the level of feature services are always considered as nullable data types and if you need to force them to be required an alternative approach would be extending current FeatureDataForm control and specifically look into the following method:
private bool HasChange(Control control, object valueInGraphic, Type type, out bool hasError)
{
}
0 Kudos
WilliamKimrey
Emerging Contributor
Thanks for the assistance.  Sadly, I'm not very good at extending controls.  I almost always mess something up and I'm kind of behind schedule already so I need to find a workaround ASAP.

In light of that, I've done the following which seems like it'll serve my purpose for now.

In the BeginSaveEdits event, I loop through the graphics to be added.  I then loop through every attribute in each graphic.  Since I know which fields have to have values in them, I set up a series of checks to see if that graphic's attributes contain those fields and if they are null.  If this is true, I show a messagebox saying the value's not set and cancel the edit.

This would work great, but for some reason, the edit is not being canceled.  The EndSaveEdits event is still firing and causing the user to start over and re-add the graphic instead of just fixing the offending attribute and saving again.

Just to clarify, to cancel the edit I put "e.Cancel = true;" in my code.  If this is not correct, please let me know.

Thanks again,
Will
0 Kudos
JenniferNery
Esri Regular Contributor
As for the e.Cancel on BeginSaveEdits, this is a related thread: http://forums.arcgis.com/threads/20915-I-set-BeginEditEventArgs.Cancel-true-but-edits-get-saved-anyw...

For workaround, you can set FeatureLayer AutoSave to False, perform your check on EditEnded and explicitly call SaveEdits().

Are you using TemplatePicker to add features? If yes, TemplatePicker also has EditCompleted event.
t.EditCompleted += (s, e) =>
{
 if (e.Action == Editor.EditAction.Add)
 {
  foreach (var edit in e.Edits)
  {
   Graphic g = edit.Graphic;
   bool requiredFieldSupplied = true;
   foreach (var item in g.Attributes)
   {
    //TODO: check required field is not null
    if (item.Key == "MyRequiredFieldName" && item.Value == null)
    {
     requiredFieldSupplied = false;
     break;
    }
   }
   FeatureLayer l = edit.Layer as FeatureLayer;
   if (requiredFieldSupplied)
    l.SaveEdits();
   else
    MessageBox.Show("MyRequiredFieldName cannot be null");
  }
 }
};
0 Kudos