2016-11-30 11 views
0

У меня есть XtraGrid, а некоторые столбцы могут маскироваться в зависимости от значения другого столбца.
Мне удалось достичь этого, установив маску в редакторе в событии CustomRowCellEdit.Как переопределить wndProc в неустанавливаемом элементе управления

Snipet ниже:

private void myGridView_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e) 
{ 
    if (e.Column.FieldName == "MyTargetField") 
    { 
     GridView gv = sender as GridView; 
     var typeValue = gv.GetRowCellValue(e.RowHandle, gv.Columns["MaskOrNotDependsOnThisField"]); 

     if (typeValue == DynamicMask) 
     { 

      var maskToApply = GetMaskForThisValue(gv.GetRowCellValue(e.RowHandle, gv.Columns["MyTargetField"])); 

      RepositoryItemTextEdit riMaskedTextEdit = new RepositoryItemTextEdit(); 
      riMaskedTextEdit.Mask.MaskType = MaskType.Simple; 
      riMaskedTextEdit.Mask.UseMaskAsDisplayFormat = true; 
      riMaskedTextEdit.Mask.SaveLiteral = false; 
      riMaskedTextEdit.Mask.EditMask = maskToApply; 
      e.RepositoryItem = riMaskedTextEdit; 
      //riMaskedTextEdit.KeyDown += EditorKeyDownDinamicMask; 
     } 
    } 
} 

Он работал как шарм, но некоторые маски могут быть динамическими (эй я не делаю requeriments!).
Так что я раскомментировал эту строку обработчика событий и создал KeyDownEventHandler.

Скажем, мои изменения маски, как пользователь держит печатая как:

999,999 для 6 цифр

999.999-9 для 7 цифр

999. (999)/99 для 8 цифр

Примечание. Мне нужно использовать KeyDown, потому что маска может предотвратить событие ValueChanged.
Я обработал keydown и смог заставить эту штуку работать нормально.

Вопрос: Как обрабатывать события Paste? (с обеих клавиатуры и мыши пастообразных событий)

Я знаю, как переопределить WNDPROC в элементе управления, я уже сделал это несколько раз.
Проблема здесь RepositoryItemTextEdit класс не является элементом управления с wndProc для переопределения.
я выкопал немного и нашел выше класс имеет

public TextEdit OwnerEdit { get; } 

И это реальный парень обработки событий.
К сожалению, devxpress оставил его как неустанавливаемый элемент.

Прямо сейчас пользователь не может заменить значение 999.999 на 999.999-9 при копировании, поскольку маска обрезает вставленное значение.
Обратите внимание, что также предотвращает событие ValueChaged к огню

ответ

0

RepositoryItemTextEdit класса используются для хранения свойств в месте экземпляра класса TextEdit. Технически TextEdit класс - это поле, которое содержит экземпляр класса TextBoxMaskBox. TextBoxMaskBox класс унаследован от System.Windows.Forms.TextBox класс.
Итак, вы можете создать себе собственные RepositoryItemTextEdit, TextEdit и TextBoxMaskBox потомки и переопределить WndProc метод в вашем собственном TextBoxMaskBox потомок.
Вот пример:

[UserRepositoryItem("RegisterPasteHandlerEdit")] 
public class RepositoryItemPasteHandlerEdit : RepositoryItemTextEdit 
{ 
    static RepositoryItemPasteHandlerEdit() 
    { 
     RegisterPasteHandlerEdit(); 
    } 

    static private readonly object EventPaste; 

    public const string CustomEditName = "PasteHandlerEdit"; 

    public RepositoryItemPasteHandlerEdit() { } 

    public override string EditorTypeName => CustomEditName; 

    public static void RegisterPasteHandlerEdit() 
    { 
     Image img = null; 
     EditorRegistrationInfo.Default.Editors.Add(new EditorClassInfo(CustomEditName, typeof(PasteHandlerEdit), typeof(RepositoryItemPasteHandlerEdit), typeof(TextEditViewInfo), new TextEditPainter(), true, img)); 
    } 

    public override void Assign(RepositoryItem item) 
    { 
     BeginUpdate(); 
     try 
     { 
      base.Assign(item); 
      var source = item as RepositoryItemPasteHandlerEdit; 
      if (source == null) return; 

      Events.AddHandler(EventPaste, source.Events[EventPaste]); 
     } 
     finally 
     { 
      EndUpdate(); 
     } 
    } 

    public event PasteEventHandler OnPaste 
    { 
     add 
     { 
      Events.AddHandler(EventPaste, value); 
     } 
     remove 
     { 
      Events.RemoveHandler(EventPaste, value); 
     } 
    } 

    protected internal void RaiseOnPaste(PasteEventArgs e) 
    { 
     if (IsLockEvents) 
      return; 

     var handler = (PasteEventHandler)Events[EventPaste]; 
     handler?.Invoke(GetEventSender(), e); 
    } 
} 

[ToolboxItem(true)] 
public class PasteHandlerEdit : TextEdit 
{ 
    static PasteHandlerEdit() 
    { 
     RepositoryItemPasteHandlerEdit.RegisterPasteHandlerEdit(); 
    } 

    public PasteHandlerEdit() { } 

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
    public new RepositoryItemPasteHandlerEdit Properties => base.Properties as RepositoryItemPasteHandlerEdit; 

    public override string EditorTypeName => RepositoryItemPasteHandlerEdit.CustomEditName; 

    protected override TextBoxMaskBox CreateMaskBoxInstance() => new PasteHandlerMaskBox(this); 

    protected override void CreateMaskBox() 
    { 
     base.CreateMaskBox(); 

     var pasteHandlerMaskBox = MaskBox as PasteHandlerMaskBox; 
     pasteHandlerMaskBox.OnPaste += PasteHandlerMaskBox_OnPaste; 
    } 

    private void PasteHandlerMaskBox_OnPaste(object sender, PasteEventArgs e) => Properties.RaiseOnPaste(e); 
} 

public class PasteHandlerMaskBox : TextBoxMaskBox 
{ 
    private const int WM_PASTE = 0x0302; 

    public PasteHandlerMaskBox(TextEdit ownerEdit) : base(ownerEdit) { } 

    public event PasteEventHandler OnPaste; 

    protected override void WndProc(ref Message msg) 
    { 
     if (msg.Msg == WM_PASTE) 
     { 
      var e = new PasteEventArgs(); 

      OnPaste?.Invoke(this, e); 

      if (e.Cancel) 
       return; 
     } 

     base.WndProc(ref msg); 
    } 
} 

public class PasteEventArgs : CancelEventArgs 
{ 
    public PasteEventArgs() { } 
    public PasteEventArgs(bool cancel) : base(cancel) { } 

    public string Text => Clipboard.GetText(); 
} 

public delegate void PasteEventHandler(object sender, PasteEventArgs e); 

В этом примере OnPaste событие добавляется к RepositoryItemPasteHandlerEdit класса. Вы можете использовать это:

private void repositoryItemPasteHandlerEdit1_OnPaste(object sender, PasteEventArgs e) 
{ 
    MessageBox.Show(e.Text); 

    if (...) // Perform some checks. 
     e.Cancel = true; 
}