Skip to content
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
42 changes: 42 additions & 0 deletions MaterialDesignThemes.Wpf/ComboBoxAssist.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using System.Windows;
using System.Windows.Controls;

namespace MaterialDesignThemes.Wpf
{
public static class ComboBoxAssist
{
#region AttachedProperty : ClassicMode
/// <summary>
/// By default ComboBox uses the wrapper popup. Popup can be switched to classic Windows desktop view by means of this attached property.
/// </summary>
Expand All @@ -23,7 +25,9 @@ public static bool GetClassicMode(DependencyObject element)
[Obsolete("ClassicMode is now obsolete and has no affect.")]
public static void SetClassicMode(DependencyObject element, bool value)
=> element.SetValue(ClassicModeProperty, value);
#endregion

#region AttachedProperty : ShowSelectedItem
/// <summary>
/// By default the selected item is displayed in the drop down list, as per Material Design specifications.
/// To change this to a behavior of hiding the selected item from the drop down list, set this attached property to false.
Expand All @@ -40,5 +44,43 @@ public static bool GetShowSelectedItem(DependencyObject element)

public static void SetShowSelectedItem(DependencyObject element, bool value)
=> element.SetValue(ShowSelectedItemProperty, value);
#endregion

#region AttachedProperty : MaxLength
/// <summary>
/// Gets or sets the maximum number of characters that can be manually entered into the text box. <br />
/// <remarks>
/// <see cref="TextBox.MaxLength"/> cannot be set for an editable ComboBox. That's why this attached property exists.
/// </remarks>
/// </summary>
public static readonly DependencyProperty MaxLengthProperty =
DependencyProperty.RegisterAttached(
name: "MaxLength",
propertyType: typeof(int),
ownerType: typeof(ComboBoxAssist),
defaultMetadata: new FrameworkPropertyMetadata(
defaultValue: 0,
propertyChangedCallback: OnMaxLenghtChanged)
);
private static void OnMaxLenghtChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
if (obj is ComboBox comboBox)
{
comboBox.Loaded +=
(s, e) =>
{
DependencyObject? textBox = comboBox.FindChild<TextBox>("PART_EditableTextBox");
if (textBox == null)
{
return;
}

textBox.SetValue(TextBox.MaxLengthProperty, args.NewValue);
};
}
}
public static int GetMaxLength(DependencyObject element) => (int)element.GetValue(MaxLengthProperty);
public static void SetMaxLength(DependencyObject element, int value) => element.SetValue(MaxLengthProperty, value);
#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
IsHitTestVisible="False"
Margin="{TemplateBinding wpf:TextFieldAssist.TextBoxViewMargin}" />
<!-- This TextBox is used in the ComboBoxAssist class. Be careful when applying changes here. -->
<TextBox
x:Name="PART_EditableTextBox"
Grid.Column="1"
Expand Down
50 changes: 50 additions & 0 deletions MaterialDesignThemes.Wpf/TreeHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,55 @@ private static bool IsAncestorTill(FrameworkElement? element, object ancestor, o

return root as Visual;
}

/// <summary>
/// Finds a Child of a given item in the visual tree.
/// </summary>
/// <param name="parent">A direct parent of the queried item.</param>
/// <typeparam name="T">The type of the queried item.</typeparam>
/// <param name="childName">x:Name or Name of child. </param>
/// <returns>The first parent item that matches the submitted type parameter.
/// If not matching item can be found,
/// a null parent is being returned.</returns>
public static T? FindChild<T>(this DependencyObject parent, string childName)
where T : DependencyObject
{
// Confirm parent and childName are valid.
if (parent == null) return null;

T? foundChild = null;

int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// If the child is not of the request child type child
if (child is not T)
{
// recursively drill down the tree
foundChild = FindChild<T>(child, childName);

// If the child is found, break so we do not overwrite the found child.
if (foundChild != null) break;
}
else if (!string.IsNullOrEmpty(childName))
{
// If the child's name is set for search
if (child is FrameworkElement frameworkElement && frameworkElement.Name == childName)
{
// if the child's name is of the request name
foundChild = (T)child;
break;
}
}
else
{
// child element found.
foundChild = (T)child;
break;
}
}
return foundChild;
}
}
}