title: WPF validation run-time generated forms
body: <p>I'm creating a WPF application which generates a form based on a model to edit it. I use reflection to go through all properties of the model to create inputfields for the properties. The GenerateForm method iterates through the properties and uses the SimpleInputFactory to generate input fields. I want to validate the input of the generated fields, but all validation methods require that you know what you are going to validate (either it's using generics or you have to specify it on the binding in the XAML). I want to validate the input based on attributes in the models. Is there any existing way of doing this? I could just make it myself, but if there is some existing way it would help.</p>
  
  <p>Thanks in advance.</p>
  
  <pre><code>    public static Grid GenerateForm(List&lt;object&gt; basisgegevensModels, AddOrEdit addOrEdit)
      {
          if (basisgegevensModels.Count &lt;= 0)
              return null;
  
          Grid formGrid = new Grid();
          formGrid.Margin = new Thickness(20,20,20,20);
          formGrid.HorizontalAlignment = HorizontalAlignment.Stretch;
          AddColumnToGrid(formGrid, GridUnitType.Star, 1);
          AddColumnToGrid(formGrid, GridUnitType.Star, 3);
          AddColumnToGrid(formGrid, GridUnitType.Star, 1);
          AddColumnToGrid(formGrid, GridUnitType.Star, 3);
          AddRowToGrid(formGrid, GridUnitType.Auto, 0);
  
  
          var propertyInfos = new List&lt;PropertyInfo&gt;();
          foreach (var propertyInfo in basisgegevensModels[0].GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance))
          {
              var visibleAttribute = propertyInfo.GetCustomAttributes(typeof(Visible), false).Cast&lt;Visible&gt;().FirstOrDefault();
  
              if (visibleAttribute == null || visibleAttribute.IsVisible)
                  propertyInfos.Add(propertyInfo);
          }
  
          int column = 0;
          int row = 0;
          foreach (var property in propertyInfos)
          {
              if (row &gt;= Math.Ceiling((decimal)propertyInfos.Count / 2) &amp;&amp; row != 0 &amp;&amp; column != 2)
              {
                  column = 2;
                  row = 0;
              }
  
              var displayNameAttribute = basisgegevensModels[0].GetType().GetProperty(property.Name).GetCustomAttributes(typeof(DisplayNameAttribute), false)
                      .Cast&lt;DisplayNameAttribute&gt;().FirstOrDefault();
              string displayName;
              if (displayNameAttribute != null)
                  displayName = displayNameAttribute.DisplayName;
              else
                  displayName = property.Name;
  
              bool isEditAllowed = true;
              if (addOrEdit == AddOrEdit.Edit)
              {
                  var editAllowed =
                      basisgegevensModels[0].GetType()
                          .GetProperty(property.Name)
                          .GetCustomAttributes(typeof (EditAllowed), false)
                          .Cast&lt;EditAllowed&gt;()
                          .FirstOrDefault();
                  if (editAllowed != null)
                      isEditAllowed = editAllowed.IsEditAllowed;
              }
  
              //add label for inputfield
              TextBlock label = SimpleInputFieldFactory.CreateTextBlock(displayName, column, row);
              label.VerticalAlignment = VerticalAlignment.Center;
              formGrid.Children.Add(label);
              column++;
              //add input field
              formGrid.Children.Add(SimpleInputFieldFactory.CreateInputField(basisgegevensModels, property, isEditAllowed, column, row, 300, HorizontalAlignment.Left));
              column--;
              row++;
              if (column == 0)
              {
                  AddRowToGrid(formGrid, GridUnitType.Auto, 0);
              }
          }
  
          return formGrid;
      }
  </code></pre>
  
  <p>SimpleInputFieldFactory Class:</p>
  
  <pre><code>public class SimpleInputFieldFactory
  {
  
      public static Control CreateInputField(List&lt;object&gt; basisgegevensModels,     PropertyInfo property, bool editAllowed, int column, int row, double     inputFieldWidth, HorizontalAlignment inputFieldHorAlignment)
      {
          Control inputField = null;
          var triggers = new List&lt;System.Windows.Interactivity.EventTrigger&gt;();
          var multiBinding = new MultiBinding();
          multiBinding.NotifyOnSourceUpdated = true;
          multiBinding.Mode = BindingMode.TwoWay;
          multiBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
  
          foreach (var basisgegevensModel in basisgegevensModels)
          {
              Binding binding = new Binding(property.Name)
              {
                  UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
                  Source = basisgegevensModel,
                  Mode = BindingMode.TwoWay
              };
              multiBinding.Bindings.Add(binding);
          }
  
          //add inputfield
          if (property.PropertyType == typeof(string) || property.PropertyType == typeof(int))
          {
              string valueAsString = "";
              if (property.GetValue(basisgegevensModels[0]) != null)
                  valueAsString = property.GetValue(basisgegevensModels[0]).ToString();
  
              inputField = CreateTextBox(valueAsString, column, row);
              triggers.Add(new System.Windows.Interactivity.EventTrigger("EditValueChanged"));
          }
          else if (property.PropertyType == typeof(bool))
          {
              bool valueAsBool = false;
              if (property.GetValue(basisgegevensModels[0]) != null)
                  valueAsBool = (bool)property.GetValue(basisgegevensModels[0]);
  
              inputField = CreateCheckBox(valueAsBool, column, row);
              triggers.Add(new System.Windows.Interactivity.EventTrigger("EditValueChanged"));
          }
          else if (property.PropertyType.BaseType == typeof(Enum))
          {
              int valueAsInt = 0;
              if (property.GetValue(basisgegevensModels[0]) != null)
                  valueAsInt = (int)property.GetValue(basisgegevensModels[0]);
  
              inputField = CreateDropDown(property.PropertyType, valueAsInt, column, row);
              triggers.Add(new System.Windows.Interactivity.EventTrigger("EditValueChanged"));
  
              ((ComboBoxEdit)inputField).SelectedIndex = valueAsInt;
              ((ComboBoxEdit)inputField).IsTextEditable = false;
          }
  
          //add general settings, bindings and triggers
          if (inputField != null)
          {
              inputField.Width = inputFieldWidth;
              inputField.HorizontalAlignment = inputFieldHorAlignment;
              inputField.Margin = new Thickness(5);
              inputField.IsEnabled = editAllowed;
              var multiEditAllowedAttribute = property.GetCustomAttributes(typeof(MultiEditAllowed), false)
                  .Cast&lt;MultiEditAllowed&gt;().FirstOrDefault();
  
              //only add binding and trigger if 1 entity is selected OR multiedit is allowed
              if (basisgegevensModels.Count == 1 || multiEditAllowedAttribute == null || multiEditAllowedAttribute.IsMultiEditAllowed)
              {
                  multiBinding.Converter = new MultiEditValueConverter();
                  inputField.SetBinding(BaseEdit.EditValueProperty, multiBinding);
  
                  foreach (var trigger in triggers)
                  {
                      var action = new ActionMessage();
                      action.MethodName = "InputChanged";
  
                      trigger.Actions.Add(action);
                      Interaction.GetTriggers(inputField).Add(trigger);
                  }
              }
              else
              {
                  inputField.IsEnabled = false;
              }
  
              return inputField;
          }
  
          return null;
      }
  
      public static List&lt;string&gt; GetEnumList(Type enumType)
      {
          if (!enumType.IsEnum)
          {
              return new List&lt;string&gt;();
          }
  
          return Enum.GetNames(enumType).ToList();
      }
  
      public static TextBlock CreateTextBlock(string text, int column, int row)
      {
          TextBlock textBlock = new TextBlock();
          textBlock.Text = text;
          Grid.SetColumn(textBlock, column);
          Grid.SetRow(textBlock, row);
  
          return textBlock;
      }
  
      private static TextEditBase CreateTextBox(string text, int column, int row)
      {
          TextEdit textBox = new TextEdit();
          textBox.Text = text;
          Grid.SetColumn(textBox, column);
          Grid.SetRow(textBox, row);
  
          return textBox;
      }
  
      private static CheckEdit CreateCheckBox(bool isChecked, int column, int row)
      {
          CheckEdit checkBox = new CheckEdit();
          checkBox.IsChecked = isChecked;
          Grid.SetColumn(checkBox, column);
          Grid.SetRow(checkBox, row);
  
          return checkBox;
      }
  
      private static ComboBoxEdit CreateDropDown(Type enumType, int value, int column, int row)
      {
          ComboBoxEdit dropDown = new ComboBoxEdit();
          foreach (var enumValue in GetEnumList(enumType))
          {
              dropDown.Items.Add(enumValue);
          }
          dropDown.SelectedIndex = value;
          Grid.SetColumn(dropDown, column);
          Grid.SetRow(dropDown, row);
  
          return dropDown;
      }
  }
  </code></pre>