Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClearTextButtonBehavior to acheive a better handling #1809

Merged
merged 2 commits into from
Feb 20, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 76 additions & 106 deletions MahApps.Metro/Controls/Helper/TextBoxHelper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
Expand All @@ -23,6 +22,10 @@ public class TextBoxHelper
public static readonly DependencyProperty UseFloatingWatermarkProperty = DependencyProperty.RegisterAttached("UseFloatingWatermark", typeof(bool), typeof(TextBoxHelper), new FrameworkPropertyMetadata(false, ButtonCommandOrClearTextChanged));
public static readonly DependencyProperty TextLengthProperty = DependencyProperty.RegisterAttached("TextLength", typeof(int), typeof(TextBoxHelper), new UIPropertyMetadata(0));
public static readonly DependencyProperty ClearTextButtonProperty = DependencyProperty.RegisterAttached("ClearTextButton", typeof(bool), typeof(TextBoxHelper), new FrameworkPropertyMetadata(false, ButtonCommandOrClearTextChanged));
/// <summary>
/// The clear text button behavior property. It sets a click event to the button if the value is true.
/// </summary>
public static readonly DependencyProperty IsClearTextButtonBehaviorEnabledProperty = DependencyProperty.RegisterAttached("IsClearTextButtonBehaviorEnabled", typeof(bool), typeof(TextBoxHelper), new FrameworkPropertyMetadata(false, IsClearTextButtonBehaviorEnabledChanged));

public static readonly DependencyProperty ButtonCommandProperty = DependencyProperty.RegisterAttached("ButtonCommand", typeof(ICommand), typeof(TextBoxHelper), new FrameworkPropertyMetadata(null, ButtonCommandOrClearTextChanged));
public static readonly DependencyProperty ButtonCommandParameterProperty = DependencyProperty.RegisterAttached("ButtonCommandParameter", typeof(object), typeof(TextBoxHelper), new FrameworkPropertyMetadata(null));
Expand Down Expand Up @@ -316,6 +319,24 @@ public static void SetClearTextButton(DependencyObject obj, bool value)
obj.SetValue(ClearTextButtonProperty, value);
}

/// <summary>
/// Gets the clear text button behavior.
/// </summary>
[AttachedPropertyBrowsableForType(typeof(Button))]
public static bool GetIsClearTextButtonBehaviorEnabled(Button d)
{
return (bool)d.GetValue(IsClearTextButtonBehaviorEnabledProperty);
}

/// <summary>
/// Sets the clear text button behavior.
/// </summary>
[AttachedPropertyBrowsableForType(typeof(Button))]
public static void SetIsClearTextButtonBehaviorEnabled(Button obj, bool value)
{
obj.SetValue(IsClearTextButtonBehaviorEnabledProperty, value);
}

public static ICommand GetButtonCommand(DependencyObject d)
{
return (ICommand)d.GetValue(ButtonCommandProperty);
Expand Down Expand Up @@ -366,6 +387,57 @@ public static void SetButtonFontFamily(DependencyObject obj, FontFamily value)
obj.SetValue(ButtonFontFamilyProperty, value);
}

private static void IsClearTextButtonBehaviorEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var button = d as Button;
if (e.OldValue != e.NewValue && button != null)
{
button.Click -= ButtonClicked;
if ((bool)e.NewValue)
{
button.Click += ButtonClicked;
}
}
}

public static void ButtonClicked(object sender, RoutedEventArgs e)
{
var button = ((Button)sender);
var parent = VisualTreeHelper.GetParent(button);
while (!(parent is TextBox || parent is PasswordBox || parent is ComboBox))
{
parent = VisualTreeHelper.GetParent(parent);
}

var command = GetButtonCommand(parent);
if (command != null && command.CanExecute(parent))
{
var commandParameter = GetButtonCommandParameter(parent);

command.Execute(commandParameter ?? parent);
}

if (GetClearTextButton(parent))
{
if (parent is TextBox)
{
((TextBox)parent).Clear();
}
else if (parent is PasswordBox)
{
((PasswordBox)parent).Clear();
}
else if (parent is ComboBox)
{
if (((ComboBox)parent).IsEditable)
{
((ComboBox)parent).Text = string.Empty;
}
((ComboBox)parent).SelectedItem = null;
}
}
}

private static void ButtonCommandOrClearTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textbox = d as TextBox;
Expand Down Expand Up @@ -406,130 +478,28 @@ private static void ButtonCommandOrClearTextChanged(DependencyObject d, Dependen
static void ComboBoxLoaded(object sender, RoutedEventArgs e)
{
var comboBox = sender as ComboBox;
if (comboBox == null || comboBox.Style == null)
return;

var template = comboBox.Template;
if (template == null)
return;

var dropDown = template.FindName("PART_DropDownToggle", comboBox) as ToggleButton;
if (dropDown == null || dropDown.Template == null)
return;

var button = dropDown.Template.FindName("PART_ClearText", dropDown) as Button;
if (button == null)
return;

if (GetClearTextButton(comboBox))
if (comboBox != null)
{
// only one event, because loaded event fires more than once, if the textbox is hosted in a tab item
button.Click -= ButtonClicked;
button.Click += ButtonClicked;
comboBox.SetValue(HasTextProperty, !string.IsNullOrWhiteSpace(comboBox.Text) || comboBox.SelectedItem != null);
}
else
{
button.Click -= ButtonClicked;
}
}

static void PassBoxLoaded(object sender, RoutedEventArgs e)
{
var passbox = sender as PasswordBox;
if (passbox == null || passbox.Style == null)
return;

var template = passbox.Template;
if (template == null) {
passbox.ApplyTemplate();
template = passbox.Template;
if (template == null)
return;
}

var button = template.FindName("PART_ClearText", passbox) as Button;
if (button == null)
return;

if (GetButtonCommand(passbox) != null || GetClearTextButton(passbox))
if (passbox != null)
{
// only one event, because loaded event fires more than once, if the textbox is hosted in a tab item
button.Click -= ButtonClicked;
button.Click += ButtonClicked;
passbox.SetValue(HasTextProperty, !string.IsNullOrWhiteSpace(passbox.Password));
}
else
{
button.Click -= ButtonClicked;
}
}

static void TextBoxLoaded(object sender, RoutedEventArgs e)
{
var textbox = sender as TextBox;
if (textbox == null || textbox.Style == null)
return;

var template = textbox.Template;
if (template == null)
return;

var button = template.FindName("PART_ClearText", textbox) as Button;
if (button == null)
return;

if (GetButtonCommand(textbox) != null || GetClearTextButton(textbox))
{
// only one event, because loaded event fires more than once, if the textbox is hosted in a tab item
button.Click -= ButtonClicked;
button.Click += ButtonClicked;
textbox.SetValue(HasTextProperty, !string.IsNullOrWhiteSpace(textbox.Text));
}
else
if (textbox != null)
{
button.Click -= ButtonClicked;
textbox.SetValue(HasTextProperty, !string.IsNullOrWhiteSpace(textbox.Text));
}
}

static void ButtonClicked(object sender, RoutedEventArgs e)
{
var button = ((Button)sender);
var parent = VisualTreeHelper.GetParent(button);
while (!(parent is TextBox || parent is PasswordBox || parent is ComboBox))
{
parent = VisualTreeHelper.GetParent(parent);
}

var command = GetButtonCommand(parent);
if (command != null && command.CanExecute(parent))
{
var commandParameter = GetButtonCommandParameter(parent);

command.Execute(commandParameter ?? parent);
}

if (GetClearTextButton(parent))
{
if (parent is TextBox)
{
((TextBox)parent).Clear();
}
else if (parent is PasswordBox)
{
((PasswordBox)parent).Clear();
}
else if (parent is ComboBox)
{
if (((ComboBox)parent).IsEditable)
{
((ComboBox)parent).Text = string.Empty;
}
((ComboBox)parent).SelectedItem = null;
}
}
}
}

}
1 change: 1 addition & 0 deletions MahApps.Metro/Styles/Controls.ComboBox.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
FontFamily="Marlett"
Content="r"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}, Path=(Controls:TextBoxHelper.ClearTextButton), Converter={StaticResource BooleanToVisibilityConverter}}"
Controls:TextBoxHelper.IsClearTextButtonBehaviorEnabled="{Binding RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}, Path=(Controls:TextBoxHelper.ClearTextButton), Mode=OneWay}"
IsTabStop="False" />
<Rectangle x:Name="BtnArrowBackground"
Grid.Column="2"
Expand Down
2 changes: 2 additions & 0 deletions MahApps.Metro/Styles/Controls.PasswordBox.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Controls:TextBoxHelper.ButtonContent), Mode=OneWay}"
Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Controls:TextBoxHelper.ClearTextButton), Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Controls:ControlsHelper.ButtonWidth), Mode=OneWay}"
Controls:TextBoxHelper.IsClearTextButtonBehaviorEnabled="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Controls:TextBoxHelper.ClearTextButton), Mode=OneWay}"
IsTabStop="False" />
<ContentPresenter x:Name="PART_CapsLockIndicator"
Grid.Row="0"
Expand Down Expand Up @@ -426,6 +427,7 @@
FontFamily="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Controls:TextBoxHelper.ButtonFontFamily), Mode=OneWay}"
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Controls:TextBoxHelper.ButtonContent), Mode=OneWay}"
Template="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Controls:TextBoxHelper.ButtonTemplate), Mode=OneWay}"
Controls:TextBoxHelper.IsClearTextButtonBehaviorEnabled="True"
IsTabStop="False" />
<ContentPresenter x:Name="PART_CapsLockIndicator"
Grid.Row="0"
Expand Down
2 changes: 2 additions & 0 deletions MahApps.Metro/Styles/Controls.TextBox.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@
FontFamily="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Controls:TextBoxHelper.ButtonFontFamily), Mode=OneWay}"
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Controls:TextBoxHelper.ButtonContent), Mode=OneWay}"
Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Controls:TextBoxHelper.ClearTextButton), Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
Controls:TextBoxHelper.IsClearTextButtonBehaviorEnabled="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Controls:TextBoxHelper.ClearTextButton), Mode=OneWay}"
IsTabStop="False" />
</Grid>
<Rectangle x:Name="DisabledVisualElement"
Expand Down Expand Up @@ -448,6 +449,7 @@
FontFamily="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Controls:TextBoxHelper.ButtonFontFamily), Mode=OneWay}"
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Controls:TextBoxHelper.ButtonContent), Mode=OneWay}"
Template="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Controls:TextBoxHelper.ButtonTemplate), Mode=OneWay}"
Controls:TextBoxHelper.IsClearTextButtonBehaviorEnabled="True"
IsTabStop="False" />
</Grid>
<Rectangle x:Name="DisabledVisualElement"
Expand Down