2012-12-06 16 views
6

Próbuję przechwycić dane wklejone w polu tekstowym WPF.Umożliwianie "wklejania danych" do pola tekstowego WPF

Na przykład użytkownik tworzy zrzut ekranu za pomocą narzędzia wycinania systemu Windows, , które automatycznie umieszcza dane obrazu w schowku. Pomysł polega na tym, aby użytkownik mógł po prostu CTRL + V na TextBox, aby móc go przechwycić, sprawdzić, czy jest to dane , a następnie zrobić, co chcę z nim.

public class PasteBehavior : Behavior<UIElement> 
{ 
    protected override void OnAttached() 
    { 
     base.OnAttached(); 
     DataObject.AddPastingHandler(AssociatedObject, new DataObjectPastingEventHandler(OnPaste)); 
    } 

    protected override void OnDetaching() 
    { 
     base.OnDetaching(); 
    } 

    private void OnPaste(object sender, DataObjectPastingEventArgs e) 
    { 
     if (e.SourceDataObject.GetDataPresent(DataFormats.Text)) 
      return; 

     var formats = e.SourceDataObject.GetFormats(); 
     foreach (var format in formats) 
      Console.WriteLine(format); 
    } 
} 

Korzystanie z zachowaniem wyżej kod nie uzyskać wyzwolone, gdy tekst jest wklejany do pola tekstowego ale wydaje TextBox nie pozwala na nic innego do wklejenia więc nawet nie osiągnie tego kodu, jeśli to nie jest tekst .

Zastanawiam się, czy istnieje właściwość, która musi być ustawiony na TextBox, lub coś innego które pozwoliłyby dane do wklejenia (chociaż nigdy TextBox może wyświetlać te dane)

Jeśli nie , jakie elementy interfejsu użytkownika pozwalają na wklejenie danych, ponieważ mogę je wykorzystać na swoją korzyść.

Aktualizacja Ktoś pisał do mnie, że będę musiał użyć RichTextBox aby umożliwić wklejenie
takiego, który nie jest coś, co mogę używać, więc postanowiłem wziąć inne podejście (nieco hacky) :

public class PasteBehavior : Behavior<UIElement> 
{ 
    protected override void OnAttached() 
    { 
     base.OnAttached(); 
     AssociatedObject.PreviewKeyDown += AssociatedObject_PreviewKeyDown; 
    } 

    void AssociatedObject_PreviewKeyDown(object sender, KeyEventArgs e) 
    { 
     if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.V) 
     { 
      if (Clipboard.ContainsData(DataFormats.Dib)) 
      { 
       using (var stream = new MemoryStream()) 
       { 
        var image = Clipboard.GetImage(); 
        var message = new ImagePastedMessage() 
        { 
         ImageData = GetImagePngData(image) 
        }; 

        Messenger.Default.Send(message); 
       } 

       e.Handled = true; 
      } 
      else if (Clipboard.ContainsFileDropList()) 
      { 
       var results = Clipboard.GetFileDropList(); 
       var filenames = new string[results.Count]; 
       results.CopyTo(filenames, 0); 

       var message = new FilesDroppedMessage() 
       { 
        Filenames = filenames 
       }; 

       Messenger.Default.Send(message); 
       e.Handled = true; 
      } 
     } 
    } 

    protected override void OnDetaching() 
    { 
     base.OnDetaching(); 
    } 

    private byte[] GetImagePngData(BitmapSource source) 
    { 
     using (var stream = new MemoryStream())    
     { 
      var encoder = new PngBitmapEncoder(); 
      encoder.Frames.Add(BitmapFrame.Create(source)); 
      encoder.Save(stream); 
      return stream.ToArray(); 
     } 
    } 
} 

To pozwala mi przenieść zdjęcia i pliki do TextBox, ale tylko używając klawiszy Ctrl + V, a nie za pomocą menu kontekstowego domyślne TextBox.

Więc nadal jestem zainteresowany wiedząc, jeśli istnieje lepszy/łatwiejszy sposób

Aktualizacja 2 podstawie roztworu przez Daniela, który działa bardzo dobrze, mam zaktualizowała OnAttached:

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

    CommandManager.AddPreviewCanExecuteHandler(AssociatedObject, onPreviewCanExecute); 
    CommandManager.AddPreviewExecutedHandler(AssociatedObject, onPreviewExecuted); 
} 

I usunięto obiekt PreviewKeyDownHandler.

+0

W jednym ze swoich fragmentów kodu, obsługujesz CTRL + V jawnie - nigdy tego nie rób! - użytkownik może na przykład wkleić skonfigurowaną inną kombinację klawiszy. Musi być szerszy komunikat "Wklej" z systemu operacyjnego, z którym możesz sobie poradzić. – BrainSlugs83

Odpowiedz

7

Można użyć zdarzeń trasowanych CommandManager.PreviewExecuted i do obsługi operacji wklejania.

Załóżmy na przykład, że chcesz zaakceptować obraz ze schowka, gdy użytkownik spróbuje wkleić go do swojego TextBox. Więc po pierwsze, określenie metod, które będą obsługiwać zarówno wydarzenia:

private void onPreviewCanExecute(object sender, CanExecuteRoutedEventArgs e) 
    { 
     // In this case, we just say it always can be executed (only for a Paste command), but you can 
     // write some checks here 
     if (e.Command == ApplicationCommands.Paste) 
     { 
      e.CanExecute = true; 
      e.Handled = true; 
     } 
    } 

    private void onPreviewExecuted(object sender, ExecutedRoutedEventArgs e) 
    { 
     // If it is a paste command.. 
     if (e.Command == ApplicationCommands.Paste) 
     { 
      // .. and the clipboard contains an image 
      if (Clipboard.ContainsImage()) 
      { 
       // proccess it somehow 
       e.Handled = true; 
      } 

     } 
    } 

Następnie, trzeba powiązać te metody za kierowane zdarzeń (to może iść w konstruktorze, na przykład):

CommandManager.AddPreviewExecutedHandler(myTextBox, onPreviewExecuted); 
CommandManager.AddPreviewCanExecuteHandler(myTextBox, onPreviewCanExecute); 

Powinno działać zarówno ze skrótem klawiaturowym, jak iz menu "przycisk".

Ważne jest, aby obsłużyć zdarzenie PreviewCanExecute. Domyślnie TextBox akceptuje tekst jako "wklejaną" treść, więc musisz jakoś oznaczyć tę treść, aby ją wkleić.

EDYCJA: Dobrze jest także usunąć "słuchaczy" z wydarzenia, jeśli możesz. Podczas korzystania z zachowań możesz to zrobić, zastępując metodę "OnDetaching" w swoim zachowaniu. Może to zapobiec wyciekom pamięci, jeśli zdarzenia nie są słabymi zdarzeniami:

protected override void OnDetaching() 
    { 
     base.OnDetaching(); 
     CommandManager.RemovePreviewExecutedHandler(myTextBox, onPreviewExecuted); 
     CommandManager.RemovePreviewCanExecuteHandler(myTextBox, onPreviewCanExecute); 
    } 
+0

Pozwól mi spróbować, za chwilę. – TimothyP

+0

Działa jak urok! Thnx! – TimothyP

+0

Nie ma za co. Cieszę się, że to zadziałało –

Powiązane problemy