这确实是一个很好的问题。正如您所指出的,它是按您注册事件处理程序的方式排序的。如果您在运行时通过反射进行操作并更改处理程序顺序,它可以按预期工作。我准备了一个场景你上面说了。
这里我定义了一个属性
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CustomAttribute : Attribute
{
private int _value;
public int Value
{
get { return _value; }
set { _value = value; }
}
private string _eventName;
public string EventName
{
get { return _eventName; }
set { _eventName = value; }
}
public CustomAttribute()
{
}
}
我创建了一个从 TextBox 扩展的自定义框
public class CustomBox : TextBox
{
public CustomBox()
{
this.PreviewTextInput += CustomBox_TextChanged;
this.PreviewTextInput += CustomBox_PreviewTextInput;
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
foreach (var item in typeof(CustomBox).GetRuntimeMethods().ToList())
{
var a = item.GetCustomAttributes();
// unsubscribe
foreach (var i in a)
{
if (i.GetType() == typeof(CustomAttribute))
{
if (((CustomAttribute)i).Value > 0)
{
RemoveEvent(((CustomAttribute)i).EventName, item.Name);
}
}
}
}
// subscribe according to your order
var methods = typeof(CustomBox).GetRuntimeMethods()
.Where(m => m.GetCustomAttributes(typeof(CustomAttribute), false).Length > 0)
.ToList();
foreach (var item in methods.OrderBy(m => ((CustomAttribute)m.GetCustomAttribute(typeof(CustomAttribute))).Value))
{
AddEvent(((CustomAttribute)item.GetCustomAttribute(typeof(CustomAttribute))).EventName, item.Name);
}
}
private void RemoveEvent(string eventName, string methodName)
{
EventInfo ev = this.GetType().GetEvent(eventName);
Type tDelegate = ev.EventHandlerType;
MethodInfo miHandler = typeof(CustomBox).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
Delegate d = Delegate.CreateDelegate(tDelegate, this, miHandler);
ev.RemoveEventHandler(this, d);
}
private void AddEvent(string eventName,string methodName)
{
EventInfo ev = this.GetType().GetEvent(eventName);
Type tDelegate = ev.EventHandlerType;
MethodInfo miHandler = typeof(CustomBox).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
Delegate d = Delegate.CreateDelegate(tDelegate, this, miHandler);
ev.AddEventHandler(this,d);
}
[CustomAttribute(EventName = "PreviewTextInput",Value = 2)]
private void CustomBox_TextChanged(object sender, TextCompositionEventArgs e)
{
this.Text = e.Text;
e.Handled = true;
}
[CustomAttribute(EventName = "PreviewTextInput", Value = 1)]
private void CustomBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (e.Text.Contains("e"))
{
e.Handled = true;
}
else e.Handled = false;
}
}
以上,即使有人创造了
this.PreviewTextInput += CustomBox_TextChanged;
操纵的处理程序
文本框文本并将其更改为非自愿文本并通过 e.handle = true 阻止另一个事件;
就在此之前。PreviewTextInput += CustomBox_PreviewTextInput;被建造,
反射会根据你的定义改变它们的顺序。