Пользовательский атрибут для настройки возможности редактирования текстового поля. - PullRequest
1 голос
/ 27 марта 2012

Я пытаюсь настроить пользовательский атрибут в C #, чтобы указать, можно ли редактировать свойство бизнес-объекта, в конечном итоге включить или отключить текстовое поле ReadOnly в XAML. Поскольку (я думал) IsEditable уже реализован в System.Windows.Controls, я подумал, что это сработает:

[AttributeUsage(AttributeTargets.Property)]
public class EditableAttribute : Attribute
{
    public EditableAttribute(bool isEditable)
    {
        this.ReadOnly = !isEditable;

    }
    public virtual bool ReadOnly { get; set; }
}

Ну, иди разберись, это не так. Я установил [Editable (false)] на строку в объекте, и она все еще доступна для редактирования. У меня такое чувство, что я даже не близко. Любая помощь или предложения будут с благодарностью!

Я знаю, что это можно настроить как стиль в xaml, но для этого случая он должен быть в бизнес-объекте.

Спасибо

Ответы [ 2 ]

1 голос
/ 28 марта 2012

Вы можете использовать BindingDecoratorBase , чтобы использовать пользовательскую привязку и использовать атрибут.

Следующий код - это просто изменение моего кода в моем проекте, который использует пользовательскую проверку . Это, вероятно, должно быть преломлено.

public interface IEditatble
{
    void SetValue(Control sender, DependencyProperty property);
}

[AttributeUsage(AttributeTargets.Property)]
public class EditableAttribute : Attribute, IEditatble
{
    public EditableAttribute(bool isEditable)
    {
        this.ReadOnly = !isEditable;

    }
    public virtual bool ReadOnly { get; set; }

    public void SetValue(System.Windows.Controls.Control sender, System.Windows.DependencyProperty property)
    {
        sender.SetValue(property, this.ReadOnly);
    }
}

Вы можете создать собственную привязку:

 public class ReadonlyBinding : BindingDecoratorBase
 {
    private DependencyProperty _targetProperty = null;
    public ReadonlyBinding()
    : base()
    {
        Binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
    }

    public override object ProvideValue(IServiceProvider provider)
    {
        // Get the binding expression
        object bindingExpression = base.ProvideValue(provider);

        // Bound items
        DependencyObject targetObject;

        // Try to get the bound items
        if (TryGetTargetItems(provider, out targetObject, out _targetProperty))
        {
            if (targetObject is FrameworkElement)
            {
                // Get the element and implement datacontext changes
                FrameworkElement element = targetObject as FrameworkElement;
                element.DataContextChanged += new DependencyPropertyChangedEventHandler(element_DataContextChanged);
            }
        }

        // Go on with the flow
        return bindingExpression;
    }

    void element_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        object datacontext = e.NewValue;
        if (datacontext != null && _targetProperty != null)
        {
            PropertyInfo property = datacontext.GetType().GetProperty(Binding.Path.Path);
            if (property != null)
            {
                var attribute = property.GetCustomAttributes(true).Where(o => o is IEditatble).FirstOrDefault();
                if (attribute != null)
                {                        
                    Control cntrl = sender as Control;
                    ((IEditatble)attribute).SetValue(cntrl, _targetProperty);
                }

            }
        }
    }
}

И вы можете использовать его как:

[Editable(true)]
public string Name { get; set; }

Xaml:

<TextBox  IsReadOnly="{local:ReadonlyBinding Path=Name}" />
1 голос
/ 27 марта 2012

Чтобы ваш EditableAttribute работал, классы TextBox должны использовать отражение в вашей модели, чтобы проверить, установлен ли атрибут, и задать необходимые свойства.Я пытаюсь сказать, что этот атрибут - не более чем метаданные, и он не контролирует рабочий процесс приложения, если только приложение не желает этого.излишество.Вам просто нужно объявить переменную IsSomePropertyReadOnly и связать ее с TextBox.

Хотя, если вы действительно хотите, вы можете написать некоторый класс-оболочку, такой как

public class ReadOrWriteText<T>
{
    private T _value;
    bool IsReadOnly { get; set; }

    public T Value 
    { 
       get { return _value; }
       set { if (IsReadOnly) return; _value = value; }
    }
}

, и связать его с IsReadOnly иЗначение свойства.Хотя это тоже излишество.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...