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