2014-05-06 111 views
0

我很難獲取WPF選項卡控件上的附加屬性。我已經實現在下面定義的CodeProject上的教程WPF選項卡控件附加屬性

http://www.codeproject.com/Articles/349140/WPF-TabControl-focus-behavior-with-invisible-tabs

定義的類。

namespace MyNamespace 
{ 

public static class TabControlBehavior 
{ 
    public static readonly DependencyProperty FocusFirstVisibleTabProperty = 
     DependencyProperty.RegisterAttached("FocusFirstVisibleTab", 
              typeof(bool), 
              typeof(TabControlBehavior), 
              new FrameworkPropertyMetadata(OnFocusFirstVisibleTabPropertyChanged)); 

/// <summary>Gets the focus first visible tab value of the given element. 

/// </summary> 
/// <param name="element">The element.</param> 
/// <returns></returns> 

public static bool GetFocusFirstVisibleTab(TabControl element) 
{ 
    if (element == null) 
    { 
     throw new ArgumentNullException("element"); 
    } 
    return (bool)element.GetValue(FocusFirstVisibleTabProperty); 
} 

/// <summary>Sets the focus first visible tab value of the given element. 

/// </summary> 
/// <param name="element">The element.</param> 
/// <param name="value">if set to <c>true</c> [value].</param> 

public static void SetFocusFirstVisibleTab(TabControl element, bool value) 
{ 
    if (element == null) 
    { 
     throw new ArgumentNullException("element"); 
    } 
    element.SetValue(FocusFirstVisibleTabProperty, value); 
} 

/// <summary>Determines whether the value of the dependency property <c>IsFocused</c> has change. 
/// </summary> 
/// <param name="d">The dependency object.</param> 
/// <param name="e">The <see 
/// cref="System.Windows.DependencyPropertyChangedEventArgs"/> 
/// instance containing the event data.</param> 
private static void OnFocusFirstVisibleTabPropertyChanged(
    DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    var tabControl = d as TabControl; 
    if (tabControl != null) 
    { 
     // Attach or detach the event handlers. 

     if ((bool)e.NewValue) 
     { 
      // Enable the attached behavior. 
      tabControl.Items.CurrentChanged += new EventHandler(TabControl_Items_CurrentChanged); 
      var collection = tabControl.Items as INotifyCollectionChanged; 
      if (collection != null) 
      { 
       collection.CollectionChanged += 
        new NotifyCollectionChangedEventHandler(TabControl_Items_CollectionChanged); 
      } 
     } 
     else 

     { 
      // Disable the attached behavior. 
      tabControl.Items.CurrentChanged -= new EventHandler(TabControl_Items_CurrentChanged); 
      var collection = tabControl.Items as INotifyCollectionChanged; 
      if (collection != null) 
      { 
       collection.CollectionChanged -= 
        new NotifyCollectionChangedEventHandler(TabControl_Items_CollectionChanged); 
      } 
      // Detach handlers from the tab items. 

      foreach (var item in tabControl.Items) 
      { 
       TabItem tab = item as TabItem; 
       if (tab != null) 
       { 
        tab.IsVisibleChanged -= 
         new DependencyPropertyChangedEventHandler(TabItem_IsVisibleChanged); 
       } 
      } 
     } 
    } 
} 

/// <summary>Handles the CollectionChanged event of the TabControl.Items collection. 
/// </summary> 
/// <param name="sender">The source of the event.</param> 

/// <param name="e">The <see 
/// cref="System.Collections.Specialized.NotifyCollectionChangedEventArgs"/> 
/// instance containing the event data.</param> 

static void TabControl_Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
{ 
    // Attach event handlers to each tab so that when the Visibility property changes of the selected tab, 
    // the focus can be shifted to the next (or previous, if not next tab available) tab. 
    var collection = sender as ItemCollection; 
    if (collection != null) 
    { 
     switch (e.Action) 
     { 
      case NotifyCollectionChangedAction.Add: 
      case NotifyCollectionChangedAction.Remove: 
      case NotifyCollectionChangedAction.Replace: 
       // Attach event handlers to the Visibility and IsEnabled properties. 

       if (e.NewItems != null) 
       { 
        foreach (var item in e.NewItems) 
        { 
         TabItem tab = item as TabItem; 
         if (tab != null) 
         { 
          tab.IsVisibleChanged += 
           new DependencyPropertyChangedEventHandler(TabItem_IsVisibleChanged); 
         } 
        } 
       } 
       // Detach event handlers from old items. 

       if (e.OldItems != null) 
       { 
        foreach (var item in e.OldItems) 
        { 
         TabItem tab = item as TabItem; 
         if (tab != null) 
         { 
          tab.IsVisibleChanged -= 
           new DependencyPropertyChangedEventHandler(TabItem_IsVisibleChanged); 
         } 
        } 
       } 
       break; 
      case NotifyCollectionChangedAction.Reset: 
       // Attach event handlers to the Visibility and IsEnabled properties. 

       foreach (var item in collection) 
       { 
        TabItem tab = item as TabItem; 
        if (tab != null) 
        { 
         tab.IsVisibleChanged += 
          new DependencyPropertyChangedEventHandler(TabItem_IsVisibleChanged); 
        } 
       } 
       break; 
      case NotifyCollectionChangedAction.Move: 
      default: 
       break; 
     } 

     // Select the first element if necessary. 

     if (collection.Count > 0 && collection.CurrentItem == null) 
     { 
      collection.MoveCurrentToFirst(); 
     } 
    } 
} 

/// <summary>Handles the CurrentChanged event of the TabControl.Items collection. 
/// </summary> 
/// <param name="sender">The source of the event.</param> 

/// <param name="e">The <see cref="System.EventArgs"/> 
/// instance containing the event data.</param> 

static void TabControl_Items_CurrentChanged(object sender, EventArgs e) 
{ 
    var collection = sender as ItemCollection; 
    if (collection != null) 
    { 
     UIElement element = collection.CurrentItem as UIElement; 
     if (element != null && element.Visibility != Visibility.Visible) 
     { 
      element.Dispatcher.BeginInvoke(new Action(() => collection.MoveCurrentToNext()), 
              System.Windows.Threading.DispatcherPriority.Input); 
     } 
    } 
} 


/// <summary>Handles the IsVisibleChanged event of the tab item. 
/// </summary> 
/// <param name="sender">The source of the event.</param> 

/// <param name="e">The <see 
/// cref="System.Windows.DependencyPropertyChangedEventArgs"/> 
/// instance containing the event data.</param> 

static void TabItem_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) 
{ 
    TabItem tab = sender as TabItem; 
    if (tab != null && tab.IsSelected && tab.Visibility != Visibility.Visible) 
    { 
     // Move to the next tab item. 

     TabControl tabControl = tab.Parent as TabControl; 
     if (tabControl != null) 
     { 
      if (!tabControl.Items.MoveCurrentToNext()) 
      { 
       // Could not move to next, try previous. 
       tabControl.Items.MoveCurrentToPrevious(); 
      } 
     } 
    } 
} 
} 
} 

我再試着設置附加依賴屬性在我的XAML代碼如下:

<Window x:Class="MyNamespace.MyApp" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d3="http://research.microsoft.com/DynamicDataDisplay/1.0" 
     xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" 
     xmlns:local="clr-namespace:MyNamespace"> 

    <Window.Resources> 
     <ResourceDictionary> 
      <Style TargetType="{x:Type TabControl}"> 
       <Setter Property="local:TabControlBehavior.FocusFirstVisibleTab" Value="True" /> 
      </Style> 
     </ResourceDictionary> 
    </Window.Resources> 
</Window> 

但是我不能編譯由於以下錯誤

MC4003:無法解析樣式屬性'FocusFirstVisibleTab'。驗證擁有的類型是Style的TargetType,還是使用Class.Property語法指定屬性。

在此先感謝您的幫助。

+0

[希望這是有用的](http://stackoverflow.com/a/7139718/352101) – Bolu

+0

嘗試使用此語法讓WPF知道它是一個附加屬性:'' – Sheridan

+0

感謝您的回覆,我試過這個無濟於事。錯誤MC3071:「(本地」是未聲明的名稱空間。 – user1400716

回答

0

該問題已通過將MyNamespace重命名爲除包含我的應用程序的名稱空間之外的內容解決。