用于设置文本框是否可编辑的自定义属性

本文关键字:编辑 自定义属性 是否 置文本 用于 | 更新日期: 2023-09-27 18:29:14

我正在尝试在C#中设置一个自定义属性,以设置业务对象属性是否可编辑,最终在XAML中启用或禁用ReadOnly文本框。由于(我认为)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中设置为一种样式,但在这种情况下,它需要在业务对象中。

感谢

用于设置文本框是否可编辑的自定义属性

您可以使用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}" />

为了使EditableAttribute工作,TextBox类应该在模型上使用反射来检查是否设置了属性并设置了必要的属性。我想说的是,属性只不过是元数据,除非应用程序愿意,否则它不会控制应用程序的工作流程

您可以从基本的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和Value属性。尽管这也有些过头了。