2016-11-09 11 views
1

私は、モデルに基づいてフォームを生成して編集するWPFアプリケーションを作成しています。私はリフレクションを使ってモデルのすべてのプロパティを調べ、プロパティの入力フィールドを作成します。 GenerateFormメソッドはプロパティを反復処理し、SimpleInputFactoryを使用して入力フィールドを生成します。生成されたフィールドの入力を検証したいのですが、すべての検証メソッドでは、検証する対象を知る必要があります(ジェネリックを使用しているか、XAMLのバインディングで指定する必要があります)。モデルの属性に基づいて入力を検証したいと思います。これを行う既存の方法はありますか?私はそれを自分で作ることができますが、既存の方法があれば助けになります。WPF検証実行時に生成されるフォーム

ありがとうございます。

public static Grid GenerateForm(List<object> basisgegevensModels, AddOrEdit addOrEdit) 
    { 
     if (basisgegevensModels.Count <= 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<PropertyInfo>(); 
     foreach (var propertyInfo in basisgegevensModels[0].GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)) 
     { 
      var visibleAttribute = propertyInfo.GetCustomAttributes(typeof(Visible), false).Cast<Visible>().FirstOrDefault(); 

      if (visibleAttribute == null || visibleAttribute.IsVisible) 
       propertyInfos.Add(propertyInfo); 
     } 

     int column = 0; 
     int row = 0; 
     foreach (var property in propertyInfos) 
     { 
      if (row >= Math.Ceiling((decimal)propertyInfos.Count/2) && row != 0 && column != 2) 
      { 
       column = 2; 
       row = 0; 
      } 

      var displayNameAttribute = basisgegevensModels[0].GetType().GetProperty(property.Name).GetCustomAttributes(typeof(DisplayNameAttribute), false) 
        .Cast<DisplayNameAttribute>().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<EditAllowed>() 
         .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; 
    } 

SimpleInputFieldFactoryクラス:

public class SimpleInputFieldFactory 
{ 

    public static Control CreateInputField(List<object> basisgegevensModels,  PropertyInfo property, bool editAllowed, int column, int row, double  inputFieldWidth, HorizontalAlignment inputFieldHorAlignment) 
    { 
     Control inputField = null; 
     var triggers = new List<System.Windows.Interactivity.EventTrigger>(); 
     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<MultiEditAllowed>().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<string> GetEnumList(Type enumType) 
    { 
     if (!enumType.IsEnum) 
     { 
      return new List<string>(); 
     } 

     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; 
    } 
} 

答えて

2

はい、あなたは検証にSystem.ComponentModel.DataAnnotationsを使用することができます。ベースの名前空間のための

ドキュメント:MSDN: System.ComponentModel.DataAnnotations

例としてはRequiredAttributeRangeAttributeが含まれます。

Microsoftはまた、次の例のErrorTemplateBindingを使用してWPFでユーザーにリアルタイムで検証フィードバックを提供する方法の優れた例を提供:MSDN: Validation in MVVM using Data Annotations

を私も自分自身の目的のために、小さなフレームワークを開発しましたこれらは基本的に基本クラスで、VMをValidationAttributeの派生属性でデコレートし、適切なBindingを使用し、残りの部分を処理します。 GitHub: ValidatingBaseViewModel

+0

ありがとうございました!それに気づいたはずです。 –

関連する問題