diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/DropDownButton/Implementation/DropDownButton.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/DropDownButton/Implementation/DropDownButton.cs new file mode 100644 index 00000000..fb46ac59 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/DropDownButton/Implementation/DropDownButton.cs @@ -0,0 +1,287 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.ComponentModel; +using System.Windows.Controls.Primitives; + +namespace Microsoft.Windows.Controls +{ + public class DropDownButton : ContentControl, ICommandSource + { + #region Members + + ToggleButton _dropDownButton; + + #endregion //Members + + #region Constructors + + static DropDownButton() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(DropDownButton), new FrameworkPropertyMetadata(typeof(DropDownButton))); + } + + public DropDownButton() + { + Keyboard.AddKeyDownHandler(this, OnKeyDown); + Mouse.AddPreviewMouseDownOutsideCapturedElementHandler(this, OnMouseDownOutsideCapturedElement); + } + + #endregion //Constructors + + #region Properties + + #region DropDownContent + + public static readonly DependencyProperty DropDownContentProperty = DependencyProperty.Register("DropDownContent", typeof(object), typeof(DropDownButton), new UIPropertyMetadata(null, OnDropDownContentChanged)); + public object DropDownContent + { + get { return (object)GetValue(DropDownContentProperty); } + set { SetValue(DropDownContentProperty, value); } + } + + private static void OnDropDownContentChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + DropDownButton dropDownButton = o as DropDownButton; + if (dropDownButton != null) + dropDownButton.OnDropDownContentChanged((object)e.OldValue, (object)e.NewValue); + } + + protected virtual void OnDropDownContentChanged(object oldValue, object newValue) + { + // TODO: Add your property changed side-effects. Descendants can override as well. + } + + #endregion //DropDownContent + + #region IsOpen + + public static readonly DependencyProperty IsOpenProperty = DependencyProperty.Register("IsOpen", typeof(bool), typeof(DropDownButton), new UIPropertyMetadata(false, OnIsOpenChanged)); + public bool IsOpen + { + get { return (bool)GetValue(IsOpenProperty); } + set { SetValue(IsOpenProperty, value); } + } + + private static void OnIsOpenChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + DropDownButton dropDownButton = o as DropDownButton; + if (dropDownButton != null) + dropDownButton.OnIsOpenChanged((bool)e.OldValue, (bool)e.NewValue); + } + + protected virtual void OnIsOpenChanged(bool oldValue, bool newValue) + { + if (newValue) + RaiseRoutedEvent(DropDownButton.OpenedEvent); + else + RaiseRoutedEvent(DropDownButton.ClosedEvent); + } + + #endregion //IsOpen + + #endregion //Properties + + #region Base Class Overrides + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + if (_dropDownButton != null) + _dropDownButton.Click -= DropDownButton_Click; + + _dropDownButton = GetTemplateChild("PART_DropDownButton") as ToggleButton; + + if (_dropDownButton != null) + _dropDownButton.Click += DropDownButton_Click; + } + + #endregion //Base Class Overrides + + #region Events + + public static readonly RoutedEvent ClickEvent = EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DropDownButton)); + public event RoutedEventHandler Click + { + add { AddHandler(ClickEvent, value); } + remove { RemoveHandler(ClickEvent, value); } + } + + public static readonly RoutedEvent OpenedEvent = EventManager.RegisterRoutedEvent("Opened", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DropDownButton)); + public event RoutedEventHandler Opened + { + add { AddHandler(OpenedEvent, value); } + remove { RemoveHandler(OpenedEvent, value); } + } + + public static readonly RoutedEvent ClosedEvent = EventManager.RegisterRoutedEvent("Closed", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DropDownButton)); + public event RoutedEventHandler Closed + { + add { AddHandler(ClosedEvent, value); } + remove { RemoveHandler(ClosedEvent, value); } + } + + #endregion //Events + + #region Event Handlers + + private void OnKeyDown(object sender, KeyEventArgs e) + { + switch (e.Key) + { + case Key.Escape: + { + CloseDropDown(); + break; + } + } + } + + private void OnMouseDownOutsideCapturedElement(object sender, MouseButtonEventArgs e) + { + CloseDropDown(); + } + + private void DropDownButton_Click(object sender, RoutedEventArgs e) + { + OnClick(); + } + + void CanExecuteChanged(object sender, EventArgs e) + { + if (Command != null) + { + RoutedCommand command = Command as RoutedCommand; + + // If a RoutedCommand. + if (command != null) + IsEnabled = command.CanExecute(CommandParameter, CommandTarget) ? true : false; + // If a not RoutedCommand. + else + IsEnabled = Command.CanExecute(CommandParameter) ? true : false; + } + } + + #endregion //Event Handlers + + #region Methods + + /// + /// Closes the drop down. + /// + private void CloseDropDown() + { + if (IsOpen) + IsOpen = false; + ReleaseMouseCapture(); + } + + protected virtual void OnClick() + { + RaiseRoutedEvent(DropDownButton.ClickEvent); + RaiseCommand(); + } + + /// + /// Raises routed events. + /// + private void RaiseRoutedEvent(RoutedEvent routedEvent) + { + RoutedEventArgs args = new RoutedEventArgs(routedEvent, this); + RaiseEvent(args); + } + + /// + /// Raises the command's Execute event. + /// + private void RaiseCommand() + { + if (Command != null) + { + RoutedCommand routedCommand = Command as RoutedCommand; + + if (routedCommand == null) + ((ICommand)Command).Execute(CommandParameter); + else + routedCommand.Execute(CommandParameter, CommandTarget); + } + } + + /// + /// Unhooks a command from the Command property. + /// + /// The old command. + /// The new command. + private void UnhookCommand(ICommand oldCommand, ICommand newCommand) + { + EventHandler handler = CanExecuteChanged; + oldCommand.CanExecuteChanged -= handler; + } + + /// + /// Hooks up a command to the CanExecuteChnaged event handler. + /// + /// The old command. + /// The new command. + private void HookUpCommand(ICommand oldCommand, ICommand newCommand) + { + EventHandler handler = new EventHandler(CanExecuteChanged); + canExecuteChangedHandler = handler; + if (newCommand != null) + newCommand.CanExecuteChanged += canExecuteChangedHandler; + } + + #endregion //Methods + + #region ICommandSource Members + + // Keeps a copy of the CanExecuteChnaged handler so it doesn't get garbage collected. + private EventHandler canExecuteChangedHandler; + + #region Command + + public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(DropDownButton), new PropertyMetadata((ICommand)null, OnCommandChanged)); + [TypeConverter(typeof(CommandConverter))] + public ICommand Command + { + get { return (ICommand)GetValue(CommandProperty); } + set { SetValue(CommandProperty, value); } + } + + private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + DropDownButton dropDownButton = d as DropDownButton; + if (dropDownButton != null) + dropDownButton.OnCommandChanged((ICommand)e.OldValue, (ICommand)e.NewValue); + } + + protected virtual void OnCommandChanged(ICommand oldValue, ICommand newValue) + { + // If old command is not null, then we need to remove the handlers. + if (oldValue != null) + UnhookCommand(oldValue, newValue); + + HookUpCommand(oldValue, newValue); + } + + #endregion //Command + + public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(DropDownButton), new PropertyMetadata(null)); + public object CommandParameter + { + get { return GetValue(CommandParameterProperty); } + set { SetValue(CommandParameterProperty, value); } + } + + public static readonly DependencyProperty CommandTargetProperty = DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(DropDownButton), new PropertyMetadata(null)); + public IInputElement CommandTarget + { + get { return (IInputElement)GetValue(CommandTargetProperty); } + set { SetValue(CommandTargetProperty, value); } + } + + #endregion //ICommandSource Members + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/DropDownButton/Themes/Generic.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/DropDownButton/Themes/Generic.xaml new file mode 100644 index 00000000..966acb7c --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/DropDownButton/Themes/Generic.xaml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml index 7c8f4e1b..5eb96a10 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml @@ -9,7 +9,8 @@ - + + diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj index 43d2e621..919d4af9 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj @@ -103,6 +103,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -180,6 +184,7 @@ +