这确实是一个非常好的问题。正如你所指出的,它是按照你如何注册事件处理程序的顺序排列的。如果你在运行时通过反射操作并改变处理程序的顺序,它可以按预期工作。我准备了一个scenerio正如你上面所说的。
这里我定义的属性
[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()
{
}
}
安迪创建自定义文件夹从文本框扩展
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阻止另一个事件;
就在this.PreviewTextInput + = CustomBox_PreviewTextInput; 反映根据您的定义更改他们的订单。
如果您创建自定义TextBox,然后使用它,然后创建PreviewTextInput,那么它将在您正在扩展的TextBox内部运行之前运行。我预览了预览键在PreviewTextInput之前运行,你可以在那里处理它。 – adminSoftDK