All the controls missing in WPF. Over 1 million downloads.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

370 lines
11 KiB

/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
namespace Xceed.Wpf.Toolkit
{
[TemplatePart( Name = PART_DropDownButton, Type = typeof( ToggleButton ) )]
public class DropDownButton : ContentControl, ICommandSource
{
private const string PART_DropDownButton = "PART_DropDownButton";
#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
private System.Windows.Controls.Primitives.ButtonBase _button;
protected System.Windows.Controls.Primitives.ButtonBase Button
{
get
{
return _button;
}
set
{
if( _button != null )
_button.Click -= DropDownButton_Click;
_button = value;
if( _button != null )
_button.Click += DropDownButton_Click;
}
}
#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();
Button = GetTemplateChild( PART_DropDownButton ) as ToggleButton;
}
#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 )
{
CanExecuteChanged();
}
#endregion //Event Handlers
#region Methods
private void CanExecuteChanged()
{
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;
}
}
/// <summary>
/// Closes the drop down.
/// </summary>
private void CloseDropDown()
{
if( IsOpen )
IsOpen = false;
ReleaseMouseCapture();
}
protected virtual void OnClick()
{
RaiseRoutedEvent( DropDownButton.ClickEvent );
RaiseCommand();
}
/// <summary>
/// Raises routed events.
/// </summary>
private void RaiseRoutedEvent( RoutedEvent routedEvent )
{
RoutedEventArgs args = new RoutedEventArgs( routedEvent, this );
RaiseEvent( args );
}
/// <summary>
/// Raises the command's Execute event.
/// </summary>
private void RaiseCommand()
{
if( Command != null )
{
RoutedCommand routedCommand = Command as RoutedCommand;
if( routedCommand == null )
( ( ICommand )Command ).Execute( CommandParameter );
else
routedCommand.Execute( CommandParameter, CommandTarget );
}
}
/// <summary>
/// Unhooks a command from the Command property.
/// </summary>
/// <param name="oldCommand">The old command.</param>
/// <param name="newCommand">The new command.</param>
private void UnhookCommand( ICommand oldCommand, ICommand newCommand )
{
EventHandler handler = CanExecuteChanged;
oldCommand.CanExecuteChanged -= handler;
}
/// <summary>
/// Hooks up a command to the CanExecuteChnaged event handler.
/// </summary>
/// <param name="oldCommand">The old command.</param>
/// <param name="newCommand">The new command.</param>
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 );
CanExecuteChanged(); //may need to call this when changing the command parameter or target.
}
#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
}
}