TextBox 붙여넣기 허용

2020. 1. 15. 13:06WPF/코드

WPF 텍스트 상자에 ‘데이터 붙여 넣기’허용

시간: 2019-05-31 16:34:56.0태그:c-2 clipboard wpf

번역: 출처번역 교정

 

WPF 텍스트 상자에 데이터를 붙여 넣으려고합니다.

예를 들어 사용자는 Windows snipping 도구를 사용하여 화면 캡처를 만들고,

자동으로 이미지 데이터를 클립 보드에 저장합니다. 여기에있는 아이디어는

사용자가 TextBox에서 CTRL V를 사용하여 가로 챌 수 있도록 허용하고, 텍스트 상자가 맞는지 확인합니다.

데이터를 가져 와서 내가 원하는대로 할 수 있습니다.

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);
   
}
}

위의 동작을 사용하면 TextBox에 텍스트를 붙여 넣을 때 코드가 트리거됩니다.

TextBox가 붙여 넣기 할 다른 것을 허용하지 않는 것 같아서 텍스트가 아닌 경우이 코드에 도달하지도 않습니다.

궁금하네요, 거기 TextBox, 또는 다른 뭔가를 설정할 필요가 속성이 무엇입니까

데이터를 붙여 넣을 수 있습니다 (TextBox에서 해당 데이터를 표시 할 수 없더라도)

그렇지 않은 경우 어떤 UI 요소를 사용하여 데이터를 붙여 넣을 수 있습니까? 그렇기 때문에이를 활용할 수도 있습니다.

최신 정보

누군가 내가 붙여 넣을 수 있도록 RichTextBox를 사용해야한다고 나에게 알렸다.

이렇게하면 사용할 수있는 것이 아니기 때문에 다른 (다소 해킹 된) 접근법을 사용하기로 결정했습니다.

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();
       
}
   
}
}

이렇게하면 이미지와 파일을 TextBox에 붙여 넣을 수 있지만

TextBox의 기본 컨텍스트 메뉴를 사용하지 않고 CTRL V 키를 사용합니다.

그래서 나는 더 나은 / 더 쉬운 방법이 있는지 아직도 알기에 관심이있다.

업데이트 2

정말 잘 작동하는 Daniel의 솔루션을 기반으로 OnAttached를 업데이트했습니다.

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

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

그리고 PreviewKeyDownHandler를 제거했습니다.

우수 답변

CommandManager.PreviewExecuted 및 CommandManager.PreviewCanExecute 라우트 된 이벤트를 사용하여 붙여 넣기 논리를 처리 할 수 ​​있습니다.

예를 들어, 사용자가 TextBox에 클립 보드를 붙여 넣으려고하면 클립 보드에서 이미지를 받아들이고 싶다고 가정 해 보겠습니다. 먼저 두 이벤트를 처리 할 메소드를 정의하십시오.

    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;
           
}

}
   
}

그런 다음 라우트 된 이벤트와 해당 메소드를 연관시켜야합니다 (예 : 생성자에 포함될 수 있음).

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

그리고 그것은 키보드 단축키와 메뉴 ‘버튼’모두와 함께 작동해야합니다.

PreviewCanExecute 이벤트를 처리하는 것이 중요합니다. 기본적으로 TextBox는 텍스트를 ‘붙여 넣을 수있는’컨텐츠로만 받아 들일 수 있으므로 붙여 넣기 위해 텍스트를 어떻게 든 표시해야합니다.

편집하다:

또한 가능한 경우 이벤트에서 ‘청취자’를 삭제하는 것이 좋습니다. 비헤이비어를 사용할 때 비헤이비어의 ‘OnDetaching’메소드를 재정 의하여이 작업을 수행 할 수 있습니다. 이벤트가 약한 이벤트가 아닌 경우 메모리 누출을 방지 할 수 있습니다.

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

 

출처: <https://codeday.me/ko/qa/20190531/679827.html>

'WPF > 코드' 카테고리의 다른 글

Paste___DataObjectPastingEventArgs  (0) 2020.02.17
WPF___Image 삽입  (0) 2020.02.17
User Exception ( example code. dll files )  (0) 2020.01.10
Delegate  (0) 2020.01.09
Caliburn.Micro  (0) 2020.01.08