Feedback

C# - WPF: Inhalt bei Doppelklick kopieren

Veröffentlicht von am 19.09.2014
(0 Bewertungen)
In Windows Forms bei Labels nur mühselig abstellbar, kann man mit dieser angefügten Eigenschaft - für WPF - einfach das Kopieren des Inhalts eines Labels bei einem Doppelklick aktivieren oder deaktivieren.
Das Kopieren funktioniert aber auch bei anderen Controls wie TextBlock und Image sowie bei Run-Elementen.

Hinweis
Ich bin der Meinung mal eine Einstellung im Windows gesehen zu haben mit der man das Kopieren bei einem Doppelklick deaktivieren kann. Wenn jemand diese Einstellung kennt, soll er diese bitte in den Kommentaren posten - ich ergänze meine Klasse entsprechend.

Benötigte Namespaces
System
System.Windows
System.Windows.Controls
System.Windows.Documents
System.Windows.Input
System.Windows.Media.Imaging
System.Linq

Beispiel
local ist der XML Namespace in dem die CopyByDoubleClickHelper-Klasse liegt.
<StackPanel>
<Label Content="Label" l:CopyByDoubleClickHelper.CopyToClipboardByDoubleClick="true"/>
<Image Source="D:\Test\testImage.png" l:CopyByDoubleClickHelper.CopyToClipboardByDoubleClick="true" Height="50" HorizontalAlignment="Left"/>
<TextBlock Text="TextBlock" l:CopyByDoubleClickHelper.CopyToClipboardByDoubleClick="true"/>
<TextBlock><Run l:CopyByDoubleClickHelper.CopyToClipboardByDoubleClick="True" Text="Run"/></TextBlock>
</StackPanel>
Snippet in VB übersetzen
/// <summary>
/// Kopiert den Inhalt eines Steuerelements in die Zwischenablage wenn doppelt darauf geklickt wird.
/// </summary>
public class CopyByDoubleClickHelper : DependencyObject
{
    /// <summary>
    /// Ruft den Wert der angefügten Eigenschaft für ein Steuerelement ab.
    /// </summary>
    /// <param name="obj">Das Steuerelement dessen angefügte Eigenschaft ausgelsen werden soll.</param>
    /// <returns><c>true</c>, wenn das Kopieren bei einem Doppelklick aktiviert ist; andernfalls <c>false</c></returns>
    public static bool GetCopyToClipboardByDoubleClick(DependencyObject obj)
    {
        return (bool)obj.GetValue(CopyToClipboardByDoubleClickProperty);
    }

    /// <summary>
    /// Setzt den Wert der angefügten Eigenschaft für ein Steuerelement.
    /// </summary>
    /// <param name="obj">Ein Steuerelement dessen angefügte Eigenschaft gesetzt weren soll.</param>
    /// <param name="value">Der zu setzende Wert der Eigenschaft.</param>
    public static void SetCopyToClipboardByDoubleClick(DependencyObject obj, bool value)
    {
        obj.SetValue(CopyToClipboardByDoubleClickProperty, value);
    }

    /// <summary>
    /// Stellt die angefügte CopyToClipboardByDoubleClick-Abhängigkeitseigenschaft dar.
    /// </summary>
    public static readonly DependencyProperty CopyToClipboardByDoubleClickProperty = DependencyProperty.RegisterAttached("CopyToClipboardByDoubleClick", typeof(bool), typeof(CopyByDoubleClickHelper), new PropertyMetadata(false, OnCopyToClipboardByDoubleClickChanged));

    private static void OnCopyToClipboardByDoubleClickChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        //Je nach Controltyp andere Events abonnieren um verschiedene Typen zu unterstützen
        if (d is Control)
            if ((bool)e.NewValue == true)
                (d as Control).PreviewMouseDoubleClick += control_PreviewMouseDoubleClick;
            else
                (d as System.Windows.Controls.Control).PreviewMouseDoubleClick -= control_PreviewMouseDoubleClick;

        else if (d is UIElement)
            if ((bool)e.NewValue == true)
                (d as UIElement).PreviewMouseLeftButtonDown += nocontrol_PreviewMouseLeftButtonDown;
            else
                (d as UIElement).PreviewMouseLeftButtonDown -= nocontrol_PreviewMouseLeftButtonDown;

        else if (d is Run)
            if ((bool)e.NewValue == true)
                (d as Run).PreviewMouseLeftButtonDown += nocontrol_PreviewMouseLeftButtonDown;
            else
                (d as Run).PreviewMouseLeftButtonDown -= nocontrol_PreviewMouseLeftButtonDown;

        else
            throw new NotSupportedException("unsupported control");//Kein passendes Control gefunden
    }

    static void nocontrol_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if (e.ClickCount == 2)
            control_PreviewMouseDoubleClick(sender, e);
    }

    static void control_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        //Typ des Contorls heraus finden und Inhalt auslesen
        object content = null;
        switch (GetKnownBaseType(sender.GetType(), "System.Windows.Controls.Image", "System.Windows.Controls.ContentControl", "System.Windows.Controls.TextBlock", "System.Windows.Documents.Run"))
        {
            case "System.Windows.Controls.Image":
                content = (sender as Image).Source;
                break;
            case "System.Windows.Controls.ContentControl":
                content = (sender as ContentControl).Content;
                break;
            case "System.Windows.Controls.TextBlock":
                content = (sender as TextBlock).Text;
                break;
            case "System.Windows.Documents.Run":
                content = (sender as Run).Text;
                break;
        }
        //Typ des Inhalts bestimmen und in die Zwischenablage setzen
        switch (GetKnownBaseType(content.GetType(), "System.String", "System.Windows.Media.Imaging.BitmapSource"))
        {
            case "System.String":
                Clipboard.SetText(content.ToString());
                break;
            case "System.Windows.Media.Imaging.BitmapSource":
                Clipboard.SetImage(content as BitmapSource);
                break;
            default:
                throw new NotSupportedException("Not supported control or unknown content type.");
        }
    }

    /// <summary>
    /// Sucht den Basistyp eines Typs, dessen voller Name bekannt ist.
    /// </summary>
    /// <param name="type">Der abgeleitete Typ.</param>
    /// <param name="knownTypes">Eine Liste mit Namen von bekannten Basistypen.</param>
    /// <returns><c>null</c> wenn kein Typ gefunden wurde; andernfalls der Name des Typs.</returns>
    static string GetKnownBaseType(Type type, params string[] knownTypes)
    {
        do
        {
            if (knownTypes.Contains(type.FullName))
                return type.FullName;
            type = type.BaseType;
        } while (type.FullName != "System.Object");
        return null;
    }
}

Kommentare zum Snippet

 

Logge dich ein, um hier zu kommentieren!