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

C# 用于设置文本框是否可编辑的自定义属性,c#,wpf,xaml,C#,Wpf,Xaml,我试图在C#中设置一个自定义属性来设置业务对象属性是否可编辑,最终在XAML中启用或禁用只读文本框。由于(我认为)IsEditable已经在System.Windows.Controls中实现,我认为这会起作用: [AttributeUsage(AttributeTargets.Property)] public class EditableAttribute : Attribute { public EditableAttribute(bool isEditable) {

我试图在C#中设置一个自定义属性来设置业务对象属性是否可编辑,最终在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中设置为样式,但在这种情况下,它需要在业务对象中


感谢您的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; }
    }
}
公共类ReadOrWriteText
{
私人T_值;
bool IsReadOnly{get;set;}
公共价值
{ 
获取{返回_值;}
设置{if(IsReadOnly)return;_value=value;}
}
}
并绑定到它的IsReadOnly和Value属性。尽管这也是一种过度使用。

您可以使用自定义绑定和属性

下面的代码只是我在使用的项目中修改代码。它可能应该折射

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}" />