2010-04-13 4 views
3

У меня есть настраиваемый элемент управления кнопки, который не является элементом Button. Возможно ли для меня реализовать эквивалент IsDefault так, чтобы команда, связанная с моим элементом управления, вызывается. Я надеялся, что это было прикрепленное свойство, которое я мог бы добавить к любому контролю, но, насколько я могу судить, это, похоже, не так. Мне повезло, если мой контроль не происходит от Button или существует ли хотя бы разумное решение?Может ли пользовательский элемент управления WPF реализовать свойство IsDefault

UPDATE: Я просто взял заглядывать с отражателем, как это делается под для кнопки, и я должен сказать, что это не самый самостоятельно explanitory код, который я видел. Похоже, что существует как минимум 3 свойства зависимостей нескольких пользовательских типов только для того, чтобы использовать концепцию Button по умолчанию. Поскольку, похоже, нет существующего способа заимствовать функциональность IsDefault, я полагаю, мне придется сузить то, что я пытаюсь достичь, чтобы я мог по крайней мере получить фокус по умолчанию и получить доступ к ключевой обработке для работы и просто игнорировать сложность, введенная в реализацию Button.IsDefault.

UPDATE: Добавлен следующий пример кода показывает мою uncessful попытку пытается предложения itowlson «s.

MyButton.xaml

<UserControl x:Class="IsDefault.MyButton" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      Height="28" 
      Width="117"> 

    <Grid> 
     <Button Click="Button_Click"> 
      <Button.Template> 
       <ControlTemplate> 
        <Border BorderThickness="2" 
          CornerRadius="12" 
          Background="DarkSlateBlue"> 
         <TextBlock Foreground="WhiteSmoke" 
            HorizontalAlignment="Center" 
            VerticalAlignment="Center">Some Text</TextBlock> 
        </Border> 
       </ControlTemplate> 
      </Button.Template> 
     </Button> 
    </Grid> 
</UserControl> 

MyButton.xaml.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 

namespace IsDefault 
{ 
    /// <summary> 
    /// Interaction logic for MyButton.xaml 
    /// </summary> 
    public partial class MyButton : UserControl 
    { 


     // Provide CLR accessors for the event 
     public event RoutedEventHandler Click 
     { 
      add { AddHandler(ClickEvent, value); } 
      remove { RemoveHandler(ClickEvent, value); } 
     } 

     // Using a RoutedEvent 
     public static readonly RoutedEvent ClickEvent = EventManager.RegisterRoutedEvent(
      "Click", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyButton)); 



     public bool IsDefault 
     { 
      get { return (bool)GetValue(IsDefaultProperty); } 
      set { SetValue(IsDefaultProperty, value); } 
     } 

     public static readonly DependencyProperty IsDefaultProperty = 
      DependencyProperty.Register(
       "IsDefault", 
       typeof(bool), 
       typeof(MyButton), 
       new PropertyMetadata(false, IsDefault_PropertyChangedCallback, null)); 


     public MyButton() 
     { 
      InitializeComponent(); 
     } 

     protected override void OnAccessKey(AccessKeyEventArgs e) 
     { 
      base.OnAccessKey(e); 

      if (e.Key == "\r") 
      { 
       if (e.IsMultiple) 
       { 
        // There are multiple controls that are currently handling the Enter key 
        MessageBox.Show("there are multiple controls handling the Enter key."); 
       } 
       else 
       { 
        RaiseEvent(new RoutedEventArgs(ClickEvent, this)); 
       } 
      } 
     } 

     private static void IsDefault_PropertyChangedCallback(
      DependencyObject d, 
      DependencyPropertyChangedEventArgs e) 
     { 
      var button = d as MyButton; 

      var isDefault = (bool)e.NewValue; 

      if (isDefault) 
      { 
       AccessKeyManager.Register("\r", button); 
      } 
      else 
      { 
       AccessKeyManager.Unregister("\r", button); 
      } 
     } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      RaiseEvent(new RoutedEventArgs(ClickEvent)); 
     } 
    } 
} 

MainWindow.xaml

<Window x:Class="IsDefault.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525" 
     xmlns:my="clr-namespace:IsDefault"> 
    <Grid> 
     <Button Content="Button" 
       Height="23" 
       HorizontalAlignment="Left" 
       Margin="224,24,0,0" 
       Name="button1" 
       VerticalAlignment="Top" 
       Width="75" /> 
     <TextBox Height="23" 
       HorizontalAlignment="Left" 
       Margin="208,94,0,0" 
       Name="textBox1" 
       VerticalAlignment="Top" 
       Width="120" /> 
     <my:MyButton Height="28" 
        HorizontalAlignment="Left" 
        Margin="232,154,0,0" 
        x:Name="myButton1" 
        VerticalAlignment="Top" 
        Width="117" 
        Click="myButton1_Click" 
        IsDefault="True"/> 
    </Grid> 
</Window> 

MainWindow.xaml.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 

namespace IsDefault 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     private void myButton1_Click(object sender, RoutedEventArgs e) 
     { 
      MessageBox.Show("My button was clicked, yay!"); 
     } 
    } 
} 

ответ

5

Все эти настройки Button.IsDefault - это вызов AccessKeyManager.Register("\r", this) (или Отменить регистрацию, если параметр установлен на false). (На самом деле, это делает немного дополнительной работы вокруг управления фокусом, но это, вероятно, не имеет решающего значения для вас.)

Таким образом, чтобы достичь подобного эффекта самостоятельно:

  • Создать свойство в IsDefault зависимостей в обычном путь.
  • В своем IsDefault PropertyChangedCallback вызовите AccessKeyManager.Register или AccessKeyManager.Unregister в соответствии с новым значением, передав "\r" (строка ввода) в качестве ключа и экземпляра элемента управления в качестве элемента.
  • Переопределить OnAccessKey, чтобы указать, как ваш элемент управления реагирует на клавишу Enter. (Например, ButtonBase переопределяет это назвать OnClick. Можно также обрабатывать AccessKeyManager.AccessKeyPressed вложенного события, но так как вы определяете пользовательский элемент управления, перекрывая OnAccessKey является аккуратнее.)
+1

Еще одно соображение: в OnAccessKey вы также можете проверить AccessKeyEventArgs.IsMultiple. Если это правда, несколько элементов управления зарегистрировали клавишу Enter в качестве ключа доступа. В этом случае вы можете по-разному реагировать, например, просто настроить фокус. –

+0

Хммм, похоже, это не работает для меня. Я думаю, что следил за всеми предложениями, но ничего не случилось, когда я нажал кнопку ввода. – jpierson

+0

Не могли бы вы разместить свой код (или просто воспроизвести, если ваш реальный код слишком длинный)? – itowlson

0

Хотя это более старым вопрос другого может все еще быть заинтересована в ответе, как и я. Итак, вот мое решение. Это основано на некоторой обратной разработке исходного справочного источника Microsoft, который я нашел (Button и ButtonBase). Я все еще новичок в WPF, поэтому много кода может быть ненужным, но оно работает!

Этот код добавляет следующие функции к UserControl (они, кажется, ближе всех связаны друг с другом):

  • IsDefault
  • IsCancel
  • Команда
  • Нажмите событие

(все комментарии в коде сделаны MS)

using System; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Input; 
using System.ComponentModel; 
using System.Windows.Automation.Peers; 
using System.Security; 
using System.Diagnostics; 

[DefaultEvent("Click")] 
public partial class MyButton : UserControl, ICommandSource { 

#region "Private Variables" 

    // Cache valid bits 
    private ControlBoolFlags _ControlBoolField; 

#endregion 

#region "Constructors" 

    static MyButton() 
    { 
     EventManager.RegisterClassHandler(
      typeof(MyButton), 
      AccessKeyManager.AccessKeyPressedEvent, 
      new AccessKeyPressedEventHandler(
       OnAccessKeyPressed)); 

     KeyboardNavigation.AcceptsReturnProperty.OverrideMetadata(
      typeof(MyButton), 
      new FrameworkPropertyMetadata(
       true)); 

     // Disable IME on button. 
     // - key typing should not be eaten by IME. 
     // - when the button has a focus, IME's disabled status should 
     // be indicated as 
     // grayed buttons on the language bar. 
     InputMethod.IsInputMethodEnabledProperty.OverrideMetadata(
      typeof(MyButton), 
      new FrameworkPropertyMetadata(
       false, 
       FrameworkPropertyMetadataOptions.Inherits)); 
    } 

#endregion 

#region "AccessKey" 

    private static void OnAccessKeyPressed(object sender, 
     AccessKeyPressedEventArgs e) 
    { 
     if (!e.Handled && e.Scope == null && e.Target == null) { 
      e.Target = sender as MyButton; 
     } 
    } 

    /// <summary> 
    /// The Access key for this control was invoked. 
    /// </summary> 
    protected override void OnAccessKey(AccessKeyEventArgs e) 
    { 
     if (e.IsMultiple) { 
      base.OnAccessKey(e); 
     } else { 
      // Don't call the base b/c we don't want to take focus 
      OnClick(); 
     } 
    } 

#endregion 

#region "Click" 

    /// <summary> 
    /// Event correspond to left mouse button click 
    /// </summary> 
    public static readonly RoutedEvent ClickEvent = 
     EventManager.RegisterRoutedEvent(
     "Click", 
     RoutingStrategy.Bubble, 
     typeof(RoutedEventHandler), 
     typeof(MyButton)); 

    /// <summary> 
    /// Add/Remove ClickEvent handler 
    /// </summary> 
    [Category("Behavior")] 
    public event RoutedEventHandler Click 
    { 
     add { 
      AddHandler(ClickEvent, value); 
     } 
     remove { 
      RemoveHandler(ClickEvent, value); 
     } 
    } 

    /// <summary> 
    /// This virtual method is called when button is clicked and 
    /// it raises the Click event 
    /// </summary> 
    private void BaseOnClick() 
    { 
     RoutedEventArgs locRoutedEventArgs = new RoutedEventArgs(
      MyButton.ClickEvent, 
      this); 
     this.RaiseEvent(locRoutedEventArgs); 
     ExecuteCommandSource(this); 
    } 

    /// <summary> 
    /// This method is called when button is clicked. 
    /// </summary> 
    private void OnClick() 
    { 
     if (AutomationPeer.ListenerExists(AutomationEvents.InvokePatternOnInvoked)) { 
      AutomationPeer locPeer = 
       UIElementAutomationPeer.CreatePeerForElement(this); 
      if (locPeer != null) { 
       locPeer.RaiseAutomationEvent(AutomationEvents.InvokePatternOnInvoked); 
      } 
     } 

     // base.OnClick should be called first. Our default command 
     // for Cancel Button to close dialog should happen after 
     // Button's click event handler has been called. 
     // If there Is excption And it Then 's a Cancel button and 
     // RoutedCommand is null, 
     // we will raise Window.DialogCancelCommand. 
     try { 
      BaseOnClick(); 
     } finally { 
      // When the Button RoutedCommand is null, if it's a 
      // Cancel Button, 
      // Window.DialogCancelCommand will be the default command. 
      // Do not assign Window.DialogCancelCommand to 
      // Button.Command. 
      // If in Button click handler user nulls the Command, 
      // we still want to provide the default behavior. 
      if (Command == null && IsCancel) { 
       // Can't invoke Window.DialogCancelCommand directly. 
       // Have to raise event. 
       // Filed bug 936090: Commanding perf issue: can't 
       // directly invoke a command. 
       ExecuteCommand(DialogCancelCommand, null, this); 
      } 
     } 
    } 

#endregion 

#region "ClickMode" 

    /// <summary> 
    ///  The DependencyProperty for the ClickMode property. 
    ///  Flags:    None 
    ///  Default Value:  ClickMode.Release 
    /// </summary> 
    public static readonly DependencyProperty ClickModeProperty = 
     DependencyProperty.Register(
     "ClickMode", 
     typeof(ClickMode), 
     typeof(MyButton), 
     new FrameworkPropertyMetadata(
      ClickMode.Release), 
     new ValidateValueCallback(
      IsValidClickMode)); 

    /// <summary> 
    ///  ClickMode specify when the Click event should fire 
    /// </summary> 
    [Bindable(true), Category("Behavior")] 
    public ClickMode ClickMode 
    { 
     get { 
      return (ClickMode)GetValue(ClickModeProperty); 
     } 
     set { 
      SetValue(ClickModeProperty, value); 
     } 
    } 

    private static bool IsValidClickMode(object valClickMode) 
    { 
     ClickMode locClickMode = (ClickMode)valClickMode; 
     return locClickMode == ClickMode.Press 
      || locClickMode == ClickMode.Release 
      || locClickMode == ClickMode.Hover; 
    } 

#endregion 

#region "KeyDown" 

    /// <summary> 
    /// This is the method that responds to the KeyDown event. 
    /// </summary> 
    /// <param name="e">Event arguments</param> 
    protected override void OnKeyDown(KeyEventArgs e) 
    { 
     base.OnKeyDown(e); 

     if (ClickMode == ClickMode.Hover) { 
      // Ignore when in hover-click mode. 
      return; 
     } 

     if (e.Key == Key.Space) { 
      // Alt+Space should bring up system menu, we shouldn't 
      // handle it. 
      if ((Keyboard.Modifiers & 
       (ModifierKeys.Control | ModifierKeys.Alt)) != 
       ModifierKeys.Alt) { 
       if ((!IsMouseCaptured) && 
        (object.ReferenceEquals(e.OriginalSource, this))) { 
        IsSpaceKeyDown = true; 
        CaptureMouse(); 
        if (ClickMode == ClickMode.Press) { 
         OnClick(); 
        } 
        e.Handled = true; 
       } 
      } 
     } else if (e.Key == Key.Enter 
      && Convert.ToBoolean(GetValue(KeyboardNavigation.AcceptsReturnProperty))) { 

      if (object.ReferenceEquals(e.OriginalSource, this)) { 
       IsSpaceKeyDown = false; 
       if (IsMouseCaptured) { 
        ReleaseMouseCapture(); 
       } 
       OnClick(); 
       e.Handled = true; 
      } 
     } else { 
      // On any other key we set IsPressed to false only if 
      // Space key is pressed 
      if (IsSpaceKeyDown) { 
       IsSpaceKeyDown = false; 
       if (IsMouseCaptured) { 
        ReleaseMouseCapture(); 
       } 
      } 
     } 
    } 

    private bool IsSpaceKeyDown 
    { 
     get { 
      return ReadControlFlag(ControlBoolFlags.IsSpaceKeyDown); 
     } 
     set { 
      WriteControlFlag(ControlBoolFlags.IsSpaceKeyDown, value); 
     } 
    } 

#endregion 

#region "Command" 

    /// <summary> 
    ///  The DependencyProperty for RoutedCommand 
    /// </summary> 
    [CommonDependencyProperty()] 
    public static readonly DependencyProperty CommandProperty = 
     DependencyProperty.Register(
     "Command", 
     typeof(ICommand), 
     typeof(MyButton), 
     new FrameworkPropertyMetadata(
      (ICommand)null, 
      new PropertyChangedCallback(
       OnCommandChanged))); 

    /// <summary> 
    /// Get or set the Command property 
    /// </summary> 
    [Bindable(true), Category("Action")] 
    [Localizability(LocalizationCategory.NeverLocalize)] 
    public ICommand Command 
    { 
     get { 
      return (ICommand)GetValue(CommandProperty); 
     } 
     set { 
      SetValue(CommandProperty, value); 
     } 
    } 

    private static void OnCommandChanged(
     DependencyObject valTarget, 
     DependencyPropertyChangedEventArgs e) 
    { 
     MyButton locMyButton = valTarget as MyButton; 
     if (locMyButton != null) { 
      locMyButton.OnCommandChanged(
       (ICommand)e.OldValue, 
       (ICommand)e.NewValue); 
     } 
    } 

    private void OnCommandChanged(
     ICommand valOldCommand, 
     ICommand valNewCommand) 
    { 
     if (valOldCommand != null) { 
      valOldCommand.CanExecuteChanged -= OnCanExecuteChanged; 
     } 
     if (valNewCommand != null) { 
      valNewCommand.CanExecuteChanged += OnCanExecuteChanged; 
     } 
     UpdateCanExecute(); 
    } 

#endregion 

#region "CommandParameter" 

    /// <summary> 
    /// The DependencyProperty for the CommandParameter 
    /// </summary> 
    [CommonDependencyProperty()] 
    public static readonly DependencyProperty CommandParameterProperty = 
     DependencyProperty.Register(
     "CommandParameter", 
     typeof(object), 
     typeof(MyButton), 
     new FrameworkPropertyMetadata(
      (object)null)); 

    /// <summary> 
    /// Reflects the parameter to pass to the CommandProperty 
    /// upon execution. 
    /// </summary> 
    [Bindable(true), Category("Action")] 
    [Localizability(LocalizationCategory.NeverLocalize)] 
    public object CommandParameter 
    { 
     get { 
      return GetValue(CommandParameterProperty); 
     } 
     set { 
      SetValue(CommandParameterProperty, value); 
     } 
    } 

#endregion 

#region "CommandTarget" 

    /// <summary> 
    ///  The DependencyProperty for Target property 
    ///  Flags:    None 
    ///  Default Value:  null 
    /// </summary> 
    [CommonDependencyProperty()] 
    public static readonly DependencyProperty CommandTargetProperty = 
     DependencyProperty.Register(
     "CommandTarget", 
     typeof(IInputElement), 
     typeof(MyButton), 
     new FrameworkPropertyMetadata(
      (IInputElement)null)); 

    /// <summary> 
    ///  The target element on which to fire the command. 
    /// </summary> 
    [Bindable(true), Category("Action")] 
    public IInputElement CommandTarget 
    { 
     get { 
      return (IInputElement)GetValue(CommandTargetProperty); 
     } 
     set { 
      SetValue(CommandTargetProperty, value); 
     } 
    } 

#endregion 

#region "CanExecute" 

    private void OnCanExecuteChanged(object valTarget, EventArgs e) 
    { 
     if (valTarget != null) { 
      UpdateCanExecute(); 
     } 
    } 

    private bool CanExecute 
    { 
     get { 
      return !ReadControlFlag(ControlBoolFlags.CommandDisabled); 
     } 
     set { 
      if (value != CanExecute) { 
       WriteControlFlag(
        ControlBoolFlags.CommandDisabled, 
        !value); 
       CoerceValue(IsEnabledProperty); 
      } 
     } 
    } 

    private void UpdateCanExecute() 
    { 
     if (Command != null) { 
      CanExecute = CanExecuteCommandSource(this); 
     } else { 
      CanExecute = true; 
     } 
    } 

#endregion 

#region "IsDefault" 

    /// <summary> 
    ///  The DependencyProperty for the IsDefault property. 
    ///  Flags:    None 
    ///  Default Value:  false 
    /// </summary> 
    public static readonly DependencyProperty IsDefaultProperty = 
     DependencyProperty.RegisterAttached(
     "IsDefault", 
     typeof(bool), 
     typeof(MyButton), 
     new UIPropertyMetadata(
      false, 
      new PropertyChangedCallback(
       OnIsDefaultChanged))); 

    /// <summary> 
    /// Specifies whether or not this button is the default button. 
    /// </summary> 
    /// <value></value> 
    public bool IsDefault 
    { 
     get { 
      return (bool)GetValue(IsDefaultProperty); 
     } 
     set { 
      SetValue(IsDefaultProperty, value); 
     } 
    } 

    private static void OnIsDefaultChanged(
     DependencyObject valTarget, 
     DependencyPropertyChangedEventArgs e) 
    { 
     MyButton locMyButton = valTarget as MyButton; 
     if (locMyButton != null) { 
      Window locWindow = Window.GetWindow(locMyButton); 
      if (locWindow == null) { 
       locWindow = Application.Current.MainWindow; 
      } 
      if (FocusChangedEventHandler == null) { 
       FocusChangedEventHandler = 
        new KeyboardFocusChangedEventHandler(
        locMyButton.OnFocusChanged); 
      } 

      if (locWindow != null) { 
       if ((bool)e.NewValue) { 
        AccessKeyManager.Register("\x000D", locMyButton); 
        KeyboardNavigation.SetAcceptsReturn(
         locMyButton, true); 
        locMyButton.UpdateIsDefaulted(
         Keyboard.FocusedElement); 
       } else { 
        AccessKeyManager.Unregister("\x000D", locMyButton); 
        KeyboardNavigation.SetAcceptsReturn(
         locMyButton, false); 
        locMyButton.UpdateIsDefaulted(null); 
       } 
      } 
     } 
    } 


    private static KeyboardFocusChangedEventHandler FocusChangedEventHandler; 

    private void OnFocusChanged(object valTarget, KeyboardFocusChangedEventArgs e) 
    { 
     UpdateIsDefaulted(Keyboard.FocusedElement); 
    } 

#endregion 

#region "IsDefaulted" 

    /// <summary> 
    ///  The key needed set a read-only property. 
    /// </summary> 
    private static readonly DependencyPropertyKey IsDefaultedPropertyKey = 
     DependencyProperty.RegisterReadOnly(
     "IsDefaulted", 
     typeof(bool), 
     typeof(MyButton), 
     new FrameworkPropertyMetadata(
      false)); 

    /// <summary> 
    ///  The DependencyProperty for the IsDefaulted property. 
    ///  Flags:    None 
    ///  Default Value:  false 
    /// </summary> 
    public static readonly DependencyProperty IsDefaultedProperty = 
     IsDefaultedPropertyKey.DependencyProperty; 

    /// <summary> 
    /// Specifies whether or not this button is the button that 
    /// would be invoked when Enter is pressed. 
    /// </summary> 
    /// <value></value> 
    public bool IsDefaulted 
    { 
     get { 
      return (bool)GetValue(IsDefaultedProperty); 
     } 
    } 

    private void UpdateIsDefaulted(IInputElement valFocusElement) 
    { 
     // If it's not a default button, or nothing is focused, 
     // or it's disabled 
     // then it's not defaulted. 
     if (!IsDefault || valFocusElement == null || !IsEnabled) { 
      SetValue(IsDefaultedPropertyKey, false); 
      return; 
     } 
     DependencyObject locFocusDependencyObj = 
      valFocusElement as DependencyObject; 
     object locThisScope = null; 
     object locFocusScope = null; 

     // If the focused thing is not in this scope then 
     // IsDefaulted = false 
     AccessKeyPressedEventArgs locEventArgs = 
      default(AccessKeyPressedEventArgs); 

     bool locIsDefaulted = false; 
     try { 
      // Step 1: Determine the AccessKey scope from currently 
      // focused element 
      locEventArgs = new AccessKeyPressedEventArgs(); 
      valFocusElement.RaiseEvent(locEventArgs); 
      locFocusScope = locEventArgs.Scope; 

      // Step 2: Determine the AccessKey scope from this button 
      locEventArgs = new AccessKeyPressedEventArgs(); 
      this.RaiseEvent(locEventArgs); 
      locThisScope = locEventArgs.Scope; 

      // Step 3: Compare scopes 
      if (object.ReferenceEquals(locThisScope, locFocusScope) 
       && (locFocusDependencyObj == null 
       || !(bool)locFocusDependencyObj.GetValue(KeyboardNavigation.AcceptsReturnProperty))) { 

       locIsDefaulted = true; 
      } 
     } finally { 
      SetValue(IsDefaultedPropertyKey, locIsDefaulted); 
     } 
    } 

#endregion 

#region "IsCancel" 

    /// <summary> 
    ///  The DependencyProperty for the IsCancel property. 
    ///  Flags:    None 
    ///  Default Value:  false 
    /// </summary> 
    public static readonly DependencyProperty IsCancelProperty = 
     DependencyProperty.Register(
     "IsCancel", 
     typeof(bool), 
     typeof(MyButton), 
     new FrameworkPropertyMetadata(
      false, 
      new PropertyChangedCallback(
       OnIsCancelChanged))); 

    /// <summary> 
    /// Specifies whether or not this button is the cancel button. 
    /// </summary> 
    /// <value></value> 
    public bool IsCancel 
    { 
     get { 
      return (bool)GetValue(IsCancelProperty); 
     } 
     set { 
      SetValue(IsCancelProperty, value); 
     } 
    } 

    private static void OnIsCancelChanged(
     DependencyObject valTarget, 
     DependencyPropertyChangedEventArgs e) 
    { 
     MyButton locMyButton = valTarget as MyButton; 
     if (locMyButton != null) { 
      if ((bool)e.NewValue) { 
       AccessKeyManager.Register("\x001B", locMyButton); 
      } else { 
       AccessKeyManager.Unregister("\x001B", locMyButton); 
      } 
     } 
    } 

#endregion 

#region "Helper Functions" 

    /// <summary> 
    /// This allows a caller to override its ICommandSource values 
    //// (used by Button and ScrollBar) 
    /// </summary> 
    static internal void ExecuteCommand(
     ICommand command, 
     object parameter, 
     IInputElement target) 
    { 
     RoutedCommand routed = command as RoutedCommand; 
     if (routed != null) { 
      if (routed.CanExecute(parameter, target)) { 
       routed.Execute(parameter, target); 
      } 
     } else if (command.CanExecute(parameter)) { 
      command.Execute(parameter); 
     } 
    } 

    static internal bool CanExecuteCommandSource(
     ICommandSource commandSource) 
    { 
     ICommand command = commandSource.Command; 
     if (command != null) { 
      object parameter = commandSource.CommandParameter; 
      IInputElement target = commandSource.CommandTarget; 
      RoutedCommand routed = command as RoutedCommand; 
      if (routed != null) { 
       if (target == null) { 
        target = commandSource as IInputElement; 
       } 
       return routed.CanExecute(parameter, target); 
      } else { 
       return command.CanExecute(parameter); 
      } 
     } 
     return false; 
    } 

    /// <summary> 
    ///  Executes the command on the given command source. 
    /// </summary> 
    /// <SecurityNote> 
    ///  Critical - calls critical function (ExecuteCommandSource). 
    ///  TreatAsSafe - always passes in false for userInitiated, 
    ////     which is safe 
    /// </SecurityNote> 
    [SecurityCritical(), SecuritySafeCritical()] 
    static internal void ExecuteCommandSource(
     ICommandSource commandSource) 
    { 
     CriticalExecuteCommandSource(commandSource, false); 
    } 

    /// <summary> 
    ///  Executes the command on the given command source. 
    /// </summary> 
    /// <SecurityNote> 
    /// Critical - sets the user initiated bit on a command, 
    ///   which is used for security purposes later. 
    ///   It is important to validate the callers of this, 
    ///   and the implementation to make sure 
    ///   that we only call MarkAsUserInitiated in the 
    ///   correct cases. 
    /// </SecurityNote> 
    [SecurityCritical()] 
    static internal void CriticalExecuteCommandSource(
     ICommandSource commandSource, 
     bool userInitiated) 
    { 
     ICommand command = commandSource.Command; 
     if (command != null) { 
      object parameter = commandSource.CommandParameter; 
      IInputElement target = commandSource.CommandTarget; 
      RoutedCommand routed = command as RoutedCommand; 
      if (routed != null) { 
       if (target == null) { 
        target = commandSource as IInputElement; 
       } 
       if (routed.CanExecute(parameter, target)) { 
        routed.Execute(parameter, target); 
       } 
      } else if (command.CanExecute(parameter)) { 
       command.Execute(parameter); 
      } 
     } 
    } 

    /// <summary> 
    /// DialogCancel Command. It closes window if it's dialog and return 
    /// false as the dialog value. 
    /// </summary> 
    /// <remarks> 
    /// Right now this is only used by Cancel Button to close the dialog. 
    static internal readonly RoutedCommand DialogCancelCommand = 
     new RoutedCommand(
     "DialogCancel", 
     typeof(Window)); 

#endregion 

#region "ControlFlags" 

    internal bool ReadControlFlag(ControlBoolFlags reqFlag) 
    { 
     return (_ControlBoolField & reqFlag) != 0; 
    } 

    internal void WriteControlFlag(ControlBoolFlags reqFlag, bool @set) 
    { 
     if (@set) 
     { 
      _ControlBoolField = _ControlBoolField | reqFlag; 
     } 
     else 
     { 
      _ControlBoolField = _ControlBoolField & (~reqFlag); 
     } 
    } 

    internal enum ControlBoolFlags : ushort 
    { 
     ContentIsNotLogical = 0x1, 
     // used in contentcontrol.cs 
     IsSpaceKeyDown = 0x2, 
     // used in ButtonBase.cs 
     HeaderIsNotLogical = 0x4, 
     // used in HeaderedContentControl.cs, HeaderedItemsControl.cs 
     CommandDisabled = 0x8, 
     // used in ButtonBase.cs, MenuItem.cs 
     ContentIsItem = 0x10, 
     // used in contentcontrol.cs 
     HeaderIsItem = 0x20, 
     // used in HeaderedContentControl.cs, HeaderedItemsControl.cs 
     ScrollHostValid = 0x40, 
     // used in ItemsControl.cs 
     ContainsSelection = 0x80, 
     // used in TreeViewItem.cs 
     VisualStateChangeSuspended = 0x100 
     // used in Control.cs 
    } 

#endregion 
} 

/// <summary> 
///  An attribute that indicates that a DependencyProperty 
///  declaration is common 
///  enough to be included in KnownTypes.cs. 
/// </summary> 
[Conditional("COMMONDPS")] 
internal sealed class CommonDependencyPropertyAttribute : Attribute 
{ 
} 
Смежные вопросы