2016-08-05 2 views
2

До сих пор я использую свойство свойства Xceed с AutoGenerateProperties="True" и указываю, какие свойства я не хочу отображать с помощью атрибута [Browsable(false)].xceed propertygrid: выберите между наборами пользовательских свойств.

Теперь у меня есть случай, когда мне нужно показать только подмножество свойств, в зависимости от значения другого свойства.

Я думаю, что ответ заключается в использовании PropertyDefinitions, как показано на рисунке here.

Но пример показывает только, как реализовать один набор PropertyDefinitions, который будет использоваться для каждого проверяемого объекта.

У вас есть подсказка или пример того, как я могу определить несколько наборов PropertyDefinitions и выбрать, когда они должны использоваться?

ответ

2

Извините, это довольно длинный ответ. Я также использовал AutoGenerateProperties="True", однако у меня была аналогичная проблема.

В результате получилось, что вы выбрали PropertyDefinition. Я сделал это программно, так как у меня возникли некоторые довольно частные случаи с желательными свойствами, создаваемыми динамически на основе содержимого коллекции где-то. Одна вещь, которую я заметил, заключалась в том, что даже с помощью программной проверки моих классов для эмуляции функции AutoGenerateProperties="True" моя работа была намного быстрее, чем их решение.

Чтобы иметь дело с видимостью, как вы просили, мне пришлось создать свой собственный Attribute, чтобы сделать предметы невидимыми с PropertyGrid.

public class VisibilityAttribute : Attribute 
{ 
    public Visibility Visibility { get; private set; } 

    public VisibilityAttribute(Visibility visibility) 
    { 
     this.Visibility = visibility; 
    } 
} 

Каждый элемент, который может быть выбран в моем проекте это собственная реализация класса PropertySetBase, который имеет определения свойств следующим образом:

[Category("Appearance"), LocalisedProperty(typeof(PropertySetBase), "LocalBackground", "LocalBackgroundDescription"), Editor(typeof(OptionalBrushEditor), typeof(OptionalBrushEditor)), 
     PropertyOrder(0)] 
    public virtual OptionalProperty<Brush> LocalBackground { get; set; } 

и логика, чтобы затем обработать PropertySetBase сек в currentPropertySelection коллекция.

private void PreparePropertyGrid() 
{ 
    PropertyDefinitionCollection propertyDefinitions = new PropertyDefinitionCollection(); 

    // This is how I determine 
    var mainPropertySet = this.currentPropertySelection.FirstOrDefault(); 

    if (mainPropertySet != null) 
    { 
     var properties = TypeDescriptor.GetProperties(mainPropertySet.GetType()); 
     // Allowing for multiple selection, if on further iterations through the selected items we will remove properties that do not exist in both PropertySets 
     bool firstIteration = true; 

     foreach (var x in this.currentPropertySelection) 
     { 
      foreach (var p in properties.Cast<PropertyDescriptor>()) 
      { 
       if (!firstIteration) 
       { 
        // Perhaps we should be checking a little more safely for TargetProperties but if the collection is empty we have bigger problems. 
        var definition = propertyDefinitions.FirstOrDefault(d => string.Equals(d.TargetProperties[0] as string, p.Name, StringComparison.Ordinal)); 

        // Someone in the selection does not have this property so we can ignore it. 
        if (definition == null) 
        { 
         continue; 
        } 

        // If this item doesn't have the property remove it from the display collection and proceed. 
        var localProperty = x.GetType().GetProperty(p.Name); 
        if (localProperty == null) 
        { 
         propertyDefinitions.Remove(definition); 
         continue; 
        } 

        // There is actually no point in proceeding if this is not the first iteration and we have checked whether the property exists. 
        continue; 
       } 

       string category = p.Category; 
       string description = p.Description; 
       string displayName = p.DisplayName ?? p.Name; 
       int? displayOrder = null; 
       bool? isBrowsable = p.IsBrowsable; 
       bool? isExpandable = null; 

       var orderAttribute = p.Attributes[typeof(PropertyOrderAttribute)] as PropertyOrderAttribute; 
       if (orderAttribute != null) 
       { 
        displayOrder = orderAttribute.Order; 
       } 

       var expandableAttribute = p.Attributes[typeof(ExpandableObjectAttribute)] as ExpandableObjectAttribute; 
       if (expandableAttribute != null) 
       { 
        isExpandable = true; 
       } 

       propertyDefinitions.Add(new PropertyDefinition 
       { 
        Category = category, 
        Description = description, 
        DisplayName = displayName, 
        DisplayOrder = displayOrder, 
        IsBrowsable = isBrowsable, 
        IsExpandable = isExpandable, 
        TargetProperties = new[] { p.Name }, 
       }); 
      } 
     } 

     firstIteration = false; 

     this.propertyGrid.PropertyDefinitions = propertyDefinitions; 
    } 
} 

Когда он пришел на самом деле показа/скрытия свойств я сделал следующее:

public void UpdateProperties(Tuple<string, bool?, Visibility?>[] newPropertyStates) 
{ 
    // Note this currently works under the assumption that an Item has to be selected in order to have a value changed. 
    this.suppressPropertyUpdates = true; 

    foreach (var property in newPropertyStates) 
    { 
     string propertyName = property.Item1; 

     string[] splits = propertyName.Split('.'); 
     if (splits.Length == 1) 
     { 
      this.propertyGrid.Properties.OfType<PropertyItem>() 
             .Where(p => string.Equals(p.PropertyDescriptor.Name, propertyName, StringComparison.Ordinal)) 
             .Map(p => 
      { 
       if (property.Item2.HasValue) 
       { 
        p.IsEnabled = property.Item2.Value; 
       } 

       if (property.Item3.HasValue) 
       { 
        p.Visibility = property.Item3.Value; 
       } 
      }); 

     } 
     else // We currently don't expect to go any lower than 1 level. 
     { 
      var parent = this.propertyGrid.Properties.OfType<PropertyItem>() 
                .Where(p => string.Equals(p.PropertyDescriptor.Name, splits[0], StringComparison.Ordinal)) 
                .FirstOrDefault(); 

      if (parent != null) 
      { 
       parent.Properties.OfType<PropertyItem>() 
           .Where(p => string.Equals(p.PropertyDescriptor.Name, splits[1], StringComparison.Ordinal)) 
           .Map(p => 
       { 
        if (property.Item2.HasValue) 
        { 
         p.IsEnabled = property.Item2.Value; 
        } 
        if (property.Item3.HasValue) 
        { 
         p.Visibility = property.Item3.Value; 
        } 
       }); 
      } 
     } 
    } 

    this.suppressPropertyUpdates = false; 
} 

Затем внутри обработчика событий PreparePropertyItem я проверить мой VisibilityAttribute и обновить элемент свойств соответственно.

void PropertyGrid_PreparePropertyItem(object sender, PropertyItemEventArgs e) 
{ 
    foreach (var x in this.currentPropertySelection) 
    { 
     // If we are in read-only mode do not allow the editing of any property. 
     if (this.IsReadOnly) 
     { 
      e.PropertyItem.IsEnabled = false; 
     } 

     string propertyName = ((PropertyItem)e.PropertyItem).PropertyDescriptor.Name; 
     PropertyInfo property = x.GetType().GetProperty(propertyName); 
     var propertyItem = e.Item as PropertyItem; 

     // If the property doesn't exist then check to see if it is on an expandable item. 
     if (property == null) 
     { 
      property = propertyItem.Instance.GetType().GetProperty(propertyName); 
     } 

     bool hasProperty = property != null; 

     if (hasProperty) 
     { 
      var browsableAttribute = property.GetCustomAttribute<BrowsableAttribute>(true); 
      if (browsableAttribute != null && 
       !browsableAttribute.Browsable) 
      { 
       e.PropertyItem.Visibility = Visibility.Collapsed; 
       e.Handled = true; 
       break; 
      } 

      var visibilityAttribute = property.GetCustomAttribute<VisibilityAttribute>(true); 
      if (visibilityAttribute != null) 
      { 
       e.PropertyItem.Visibility = visibilityAttribute.Visibility; 
       e.Handled = true; 
      } 

      var independentAttribute = property.GetCustomAttribute<IndependentAttribute>(true); 
      // If a property is marked as being independent then we do not allow editing if multiple items are selected 
      if (independentAttribute != null && 
       this.currentPropertySelection.Length > 1) 
      { 
       e.PropertyItem.IsEnabled = false; 
       e.Handled = true; 
       break; 
      } 
     } 
    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^