Question

I am having difficulty getting an attached property working on a WPF Tab Control. I have implemented the class defined in the CodeProject tutorial

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

defined below.

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();
            }
        }
    }
}
}
}

I then try to set the attached dependency property in my xaml code as follows :

<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>

However I can't compile due to the following error

MC4003: Cannot resolve the Style Property 'FocusFirstVisibleTab'. Verify that the owning type is the Style's TargetType, or use Class.Property syntax to specify the Property.

Thanks in advance for any help.

Était-ce utile?

La solution

The problem was resolved by renaming MyNamespace to something other than the namespace containing my application.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top