diff --git a/Source/NETworkManager.Utilities.WPF/PermissionToolTipHelper.cs b/Source/NETworkManager.Utilities.WPF/PermissionToolTipHelper.cs
new file mode 100644
index 0000000000..f6f679a287
--- /dev/null
+++ b/Source/NETworkManager.Utilities.WPF/PermissionToolTipHelper.cs
@@ -0,0 +1,91 @@
+using System.Windows;
+using System.Windows.Controls;
+
+namespace NETworkManager.Utilities.WPF;
+
+///
+/// Attached-property helper to show a hint (e.g. "requires elevated rights") as tooltip on a control,
+/// which is disabled because the application is missing a permission (e.g. not running as administrator).
+/// The tooltip is also shown while the control is disabled and only if
+/// is . An existing tooltip of the control is never overwritten.
+///
+public static class PermissionToolTipHelper
+{
+ ///
+ /// Resource key of the tooltip style (limits the width and wraps long text).
+ /// Defined in "Resources/Styles/ToolTipStyles.xaml" of the application.
+ ///
+ private const string ToolTipStyleKey = "WrapToolTip";
+
+ ///
+ /// Text of the tooltip, which is shown if the permission is missing.
+ ///
+ public static readonly DependencyProperty TextProperty =
+ DependencyProperty.RegisterAttached(
+ "Text",
+ typeof(string),
+ typeof(PermissionToolTipHelper),
+ new PropertyMetadata(null, OnChanged));
+
+ public static void SetText(FrameworkElement element, string value) =>
+ element.SetValue(TextProperty, value);
+
+ public static string GetText(FrameworkElement element) =>
+ (string)element.GetValue(TextProperty);
+
+ ///
+ /// Indicates whether the permission is available (e.g. running as administrator).
+ /// Defaults to , so no tooltip is shown until the binding is resolved.
+ ///
+ public static readonly DependencyProperty HasPermissionProperty =
+ DependencyProperty.RegisterAttached(
+ "HasPermission",
+ typeof(bool),
+ typeof(PermissionToolTipHelper),
+ new PropertyMetadata(true, OnChanged));
+
+ public static void SetHasPermission(FrameworkElement element, bool value) =>
+ element.SetValue(HasPermissionProperty, value);
+
+ public static bool GetHasPermission(FrameworkElement element) =>
+ (bool)element.GetValue(HasPermissionProperty);
+
+ ///
+ /// Indicates whether the tooltip was set by this helper (to only clear our own tooltip).
+ ///
+ private static readonly DependencyProperty IsAppliedProperty =
+ DependencyProperty.RegisterAttached(
+ "IsApplied",
+ typeof(bool),
+ typeof(PermissionToolTipHelper),
+ new PropertyMetadata(false));
+
+ private static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is not FrameworkElement element)
+ return;
+
+ var text = GetText(element);
+ var isApplied = (bool)element.GetValue(IsAppliedProperty);
+
+ if (!GetHasPermission(element) && !string.IsNullOrEmpty(text))
+ {
+ // Don't overwrite a tooltip that was set on the control itself
+ if (!isApplied && element.ToolTip != null)
+ return;
+
+ var toolTip = new ToolTip { Content = text };
+ toolTip.SetResourceReference(FrameworkElement.StyleProperty, ToolTipStyleKey);
+
+ element.ToolTip = toolTip;
+ ToolTipService.SetShowOnDisabled(element, true);
+ element.SetValue(IsAppliedProperty, true);
+ }
+ else if (isApplied)
+ {
+ element.ClearValue(FrameworkElement.ToolTipProperty);
+ element.ClearValue(ToolTipService.ShowOnDisabledProperty);
+ element.SetValue(IsAppliedProperty, false);
+ }
+ }
+}
diff --git a/Source/NETworkManager/Resources/Styles/RectangleStyles.xaml b/Source/NETworkManager/Resources/Styles/RectangleStyles.xaml
index 3a2365c7de..475520e48b 100644
--- a/Source/NETworkManager/Resources/Styles/RectangleStyles.xaml
+++ b/Source/NETworkManager/Resources/Styles/RectangleStyles.xaml
@@ -66,7 +66,7 @@
+
+
diff --git a/Source/NETworkManager/Views/DiscoveryProtocolView.xaml b/Source/NETworkManager/Views/DiscoveryProtocolView.xaml
index 9c49ffc957..692cc16a9a 100644
--- a/Source/NETworkManager/Views/DiscoveryProtocolView.xaml
+++ b/Source/NETworkManager/Views/DiscoveryProtocolView.xaml
@@ -8,6 +8,7 @@
xmlns:converters="clr-namespace:NETworkManager.Converters;assembly=NETworkManager.Converters"
xmlns:viewModels="clr-namespace:NETworkManager.ViewModels"
xmlns:localization="clr-namespace:NETworkManager.Localization.Resources;assembly=NETworkManager.Localization"
+ xmlns:wpfHelpers="clr-namespace:NETworkManager.Utilities.WPF;assembly=NETworkManager.Utilities.WPF"
xmlns:settings="clr-namespace:NETworkManager.Settings;assembly=NETworkManager.Settings"
mc:Ignorable="d" d:DataContext="{d:DesignInstance viewModels:DiscoveryProtocolViewModel}">
@@ -65,6 +66,8 @@