Skip to content

Instantly share code, notes, and snippets.

@BYJRK
Last active March 25, 2025 01:20
Show Gist options
  • Select an option

  • Save BYJRK/b49db5538a006d17fe4858217b330382 to your computer and use it in GitHub Desktop.

Select an option

Save BYJRK/b49db5538a006d17fe4858217b330382 to your computer and use it in GitHub Desktop.
Livet Handy Snippets
public static class DynamicMethodInvoker
{
public static void Invoke(object targetObject, string methodName)
{
if (targetObject == null)
throw new ArgumentNullException(nameof(targetObject));
if (methodName == null)
throw new ArgumentNullException(nameof(methodName));
var targetObjectType = targetObject.GetType();
var methodInfo = targetObjectType
.GetMethods()
.FirstOrDefault(method =>
method.Name == methodName
&& method.GetParameters().Length == 0
&& method.ReturnType == typeof(void)
);
if (methodInfo == null)
{
throw new ArgumentException("Method not found.", nameof(methodName));
}
methodInfo.Invoke(targetObject, Array.Empty<object>());
}
}
using Microsoft.Xaml.Behaviors;
using System.Windows;
using System.Windows.Controls;
// Source: https://github.com/runceel/Livet/blob/master/LivetCask.Behaviors/ControlBinding/PasswordBoxBindingSupportBehavior.cs
public class PasswordBoxBindingSupportBehavior : Behavior<PasswordBox>
{
public static readonly DependencyProperty PasswordProperty = DependencyProperty.Register(
nameof(Password),
typeof(string),
typeof(PasswordBoxBindingSupportBehavior),
new FrameworkPropertyMetadata(
string.Empty,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
SourcePasswordChanged
)
);
public string Password
{
get { return (string)GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
private static void SourcePasswordChanged(
DependencyObject sender,
DependencyPropertyChangedEventArgs e
)
{
var associatedObject = (sender as PasswordBoxBindingSupportBehavior)?.AssociatedObject;
if (associatedObject == null)
return;
var newValue = e.NewValue as string;
if (associatedObject.Password != newValue)
associatedObject.Password = newValue ?? string.Empty;
}
private void ControlPasswordChanged(object sender, RoutedEventArgs e)
{
if (sender == null)
throw new ArgumentNullException(nameof(sender));
var pb = (PasswordBox)sender;
if (Password != pb.Password)
Password = pb.Password;
}
protected override void OnAttached()
{
base.OnAttached();
SourcePasswordChanged(
this,
new DependencyPropertyChangedEventArgs(PasswordProperty, null, Password)
);
if (AssociatedObject != null)
AssociatedObject.PasswordChanged += ControlPasswordChanged;
}
}
using Microsoft.Xaml.Behaviors;
using System.Windows;
using System.Windows.Controls;
// Source: https://github.com/runceel/Livet/blob/master/LivetCask.Behaviors/ControlBinding/TextBoxBindingSupportBehavior.cs
public class TextBoxBindingSupportBehavior : Behavior<TextBox>
{
public static readonly DependencyProperty SelectedTextProperty = DependencyProperty.Register(
nameof(SelectedText),
typeof(string),
typeof(TextBoxBindingSupportBehavior),
new FrameworkPropertyMetadata(
string.Empty,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
SelectedTextChangedHandler
)
);
public static readonly DependencyProperty SelectionLengthProperty = DependencyProperty.Register(
nameof(SelectionLength),
typeof(int),
typeof(TextBoxBindingSupportBehavior),
new FrameworkPropertyMetadata(
0,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
SelectionLengthChangedHandler
)
);
public static readonly DependencyProperty SelectionStartProperty = DependencyProperty.Register(
nameof(SelectionStart),
typeof(int),
typeof(TextBoxBindingSupportBehavior),
new FrameworkPropertyMetadata(
0,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
SelectionStartChangedHandler
)
);
public string SelectedText
{
get { return (string)GetValue(SelectedTextProperty); }
set { SetValue(SelectedTextProperty, value); }
}
public int SelectionLength
{
get { return (int)(GetValue(SelectionLengthProperty) ?? default(int)); }
set { SetValue(SelectionLengthProperty, value); }
}
public int SelectionStart
{
get { return (int)(GetValue(SelectionStartProperty) ?? default(int)); }
set { SetValue(SelectionStartProperty, value); }
}
private static void SelectedTextChangedHandler(
DependencyObject sender,
DependencyPropertyChangedEventArgs e
)
{
var thisObject = sender as TextBoxBindingSupportBehavior;
var associatedObject = thisObject?.AssociatedObject;
var s = e.NewValue as string;
if (associatedObject != null && associatedObject.SelectedText != s && s != null)
associatedObject.SelectedText = s;
}
private static void SelectionLengthChangedHandler(
DependencyObject sender,
DependencyPropertyChangedEventArgs e
)
{
var associatedObject = (sender as TextBoxBindingSupportBehavior)?.AssociatedObject;
if (associatedObject == null)
return;
var newValue = (int)(e.NewValue ?? default(int));
if (associatedObject.SelectionLength != newValue)
associatedObject.SelectionLength = newValue;
}
private static void SelectionStartChangedHandler(
DependencyObject sender,
DependencyPropertyChangedEventArgs e
)
{
var associatedObject = (sender as TextBoxBindingSupportBehavior)?.AssociatedObject;
if (associatedObject == null)
return;
var newValue = (int)(e.NewValue ?? default(int));
if (associatedObject.SelectionStart != newValue)
associatedObject.SelectionStart = newValue;
}
private void SelectionChangedHandler(object sender, RoutedEventArgs e)
{
if (sender == null)
throw new ArgumentNullException(nameof(sender));
var textBox = (TextBox)sender;
if (SelectedText != textBox.SelectedText)
SelectedText = textBox.SelectedText;
if (SelectionStart != textBox.SelectionStart)
SelectionStart = textBox.SelectionStart;
if (SelectionLength != textBox.SelectionLength)
SelectionLength = textBox.SelectionLength;
}
protected override void OnAttached()
{
SelectedTextChangedHandler(
this,
new DependencyPropertyChangedEventArgs(SelectedTextProperty, null, SelectedText)
);
SelectionStartChangedHandler(
this,
new DependencyPropertyChangedEventArgs(SelectionStartProperty, null, SelectionStart)
);
SelectionLengthChangedHandler(
this,
new DependencyPropertyChangedEventArgs(SelectionLengthProperty, null, SelectionLength)
);
if (AssociatedObject != null)
AssociatedObject.SelectionChanged += SelectionChangedHandler;
}
}
using Microsoft.Xaml.Behaviors;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
// Source: https://github.com/runceel/Livet/blob/master/LivetCask.Behaviors/WindowCloseCancelBehavior.cs
public class WindowCloseCancelBehavior : Behavior<Window>
{
public static readonly DependencyProperty CanCloseProperty = DependencyProperty.Register(
nameof(CanClose),
typeof(bool),
typeof(WindowCloseCancelBehavior),
new PropertyMetadata(true)
);
public static readonly DependencyProperty CloseCanceledCallbackCommandProperty =
DependencyProperty.Register(
nameof(CloseCanceledCallbackCommand),
typeof(ICommand),
typeof(WindowCloseCancelBehavior),
new PropertyMetadata(null)
);
public static readonly DependencyProperty CloseCanceledCallbackMethodTargetProperty =
DependencyProperty.Register(
nameof(CloseCanceledCallbackMethodTarget),
typeof(object),
typeof(WindowCloseCancelBehavior),
new PropertyMetadata(null)
);
public static readonly DependencyProperty CloseCanceledCallbackMethodNameProperty =
DependencyProperty.Register(
nameof(CloseCanceledCallbackMethodName),
typeof(string),
typeof(WindowCloseCancelBehavior),
new PropertyMetadata(null)
);
private readonly MethodBinder _callbackMethod = new MethodBinder();
public bool CanClose
{
get => (bool)(GetValue(CanCloseProperty) ?? default(bool));
set => SetValue(CanCloseProperty, value);
}
public ICommand? CloseCanceledCallbackCommand
{
get => (ICommand)GetValue(CloseCanceledCallbackCommandProperty);
set => SetValue(CloseCanceledCallbackCommandProperty, value);
}
public object? CloseCanceledCallbackMethodTarget
{
get => GetValue(CloseCanceledCallbackMethodTargetProperty);
set => SetValue(CloseCanceledCallbackMethodTargetProperty, value);
}
public string? CloseCanceledCallbackMethodName
{
get => (string)GetValue(CloseCanceledCallbackMethodNameProperty);
set => SetValue(CloseCanceledCallbackMethodNameProperty, value);
}
protected override void OnAttached()
{
var associatedObject = AssociatedObject ?? throw new InvalidOperationException();
associatedObject.Closing += OnClosing;
}
protected void OnClosing(object? sender, CancelEventArgs e)
{
ArgumentNullException.ThrowIfNull(e, nameof(e));
if (CanClose)
return;
if (CloseCanceledCallbackCommand != null && CloseCanceledCallbackCommand.CanExecute(null))
CloseCanceledCallbackCommand.Execute(null);
if (CloseCanceledCallbackMethodTarget != null && CloseCanceledCallbackMethodName != null)
DynamicMethodInvoker.Invoke(CloseCanceledCallbackMethodTarget, CloseCanceledCallbackMethodName);
e.Cancel = true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment