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

时间:2012-03-27 18:40:58

标签: c# wpf xaml

我正在尝试在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中设置为样式,但是对于这种情况,它需要在业务对象中。

由于

2 个答案:

答案 0 :(得分:1)

要使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属性。虽然这也是一种矫枉过正。

答案 1 :(得分:1)

您可以使用BindingDecoratorBase来使用自定义绑定并使用属性。

以下代码只是我修改了使用custom validation 的项目中的代码。它可能应该被重新折射。

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