2011-08-25 3 views
3

제가 실수를하지 않는 한 (내가 무엇이든지간에) TabControl의 버그가 있고 TabItems의 가시성에 관련된 버그가 있습니다. 버그를 재현하는 XAML은 다음과 같습니다.이 tabcontrol/tabitem 버그에 대한 회피책이 있습니까

<UserControl x:Class="TabControl_bug.MainPage" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 
    mc:Ignorable="d" 
    d:DesignHeight="300" d:DesignWidth="400"> 
    <Grid x:Name="LayoutRoot" Background="White"> 
     <sdk:TabControl> 
      <sdk:TabItem Header="tabItem1" Visibility="Collapsed"> 
       <TextBlock Text="TabItem1 which should not be visible" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
      </sdk:TabItem> 
      <sdk:TabItem Header="tabItem2"> 
       <TextBlock Text="TabItem2 which should be visible" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
      </sdk:TabItem> 
     </sdk:TabControl> 
    </Grid> 
</UserControl> 

이 코드를 실행하면, 당신은 TabItem2은 "선택"되지 않는 것을 볼 수 있습니다 때문에 표시되는 내용이 표시되지해야

TabItem의 1

탭을 선택하면 당연히 TabItem2 콘텐츠가 표시되고 tabItem1로 돌아갈 방법이 없지만 문제는 처음 화면에 표시됩니다.

SelectedIndex 속성을 1로 설정하면 올바른 내용이 표시됩니다. Howerver 나는 XAML에서 탭 중 어느 것이 먼저 선택되어야하는지 모른다.

이 문제점의 해결 방법은 무엇입니까? 이상적으로, tabcontrol은 그것이 처음 보이는 tabitem을 미리 선택했다.

+0

수 우리 분명히 뭔가까지. 기본 선택 항목은 첫 번째 항목 (색인 0)이라는 것을 알고 있습니다. 잠시 동안 탭 항목이 축소되지 않았다고 가정합니다. "어느 탭을 먼저 선택해야합니까?" 또는 기본값이 맞습니까? 기본값이 올바른 경우 기본값이 실제로 축소되어 있으면 사용 가능한 다음 탭을 선택해야합니다. Xaml에서 축소 된 것을 볼 수 있으므로 SelectedIndex가 무엇인지 확인할 수 있습니다. – AnthonyWJones

+0

코드의 결과 여야 할 내용이 무엇인지 알 수없는 경우 해당 코드가 SelectedIndex를 설정하면 안됩니까? – AnthonyWJones

+1

해결 방법 : TabControl의 Loaded 이벤트를 구독하면 첫 번째 표시된 TabItem이 발견되고 선택한 것으로 표시됩니다. – NestorArturo

답변

1

나는 MainPage 생성자에서 샘플 solution.For 다음 발견했습니다

tabControl.SetValue(TabControl.SelectedContentProperty, null); 

는 또한로드 이벤트에서 해당 작업을 수행 할 수 있습니다.

TabControl.SelectedContent 속성에는 공용 설정자가 없으므로 SelectedContentProperty를 직접 설정할 수 있습니다.

편집 :이 기능에 대한

동작 :

public class UnselectContentBehavior : Behavior<TabControl> 
{ 
     protected override void OnAttached() 
     { 
      base.OnAttached(); 
      AssociatedObject.Loaded += OnLoaded; 
     } 

     private void OnLoaded(object sender, RoutedEventArgs e) 
     { 
      AssociatedObject.SetValue(TabControl.SelectedContentProperty, null); 
     } 

     protected override void OnDetaching() 
     { 
      base.OnDetaching(); 
      AssociatedObject.Loaded -= OnLoaded; 
     } 
} 

샘플을 사용 : 문제를 해결하려고 할 때

 <sdk:TabControl x:Name="tabControl"> 
      <sdk:TabItem Header="tabItem1" Visibility="Collapsed"> 
       <TextBlock Text="TabItem1 which should not be visible" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
      </sdk:TabItem> 
      <sdk:TabItem Header="tabItem2"> 
       <TextBlock Text="TabItem2 which should be visible" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
      </sdk:TabItem> 

      <i:Interaction.Behaviors> 
       <b:UnselectContentBehavior/> 
      </i:Interaction.Behaviors> 
     </sdk:TabControl> 
0

나는이 질문에 건너 온은 here을 설명했다. 나는 두 가지 경우 모두 다루는 합리적인 해결책을 발견했다. TabControl에서 연결된 속성 "SelectOnlyVisibleTabs"가 true로 설정되어 동작을 수정합니다. 런타임 중에 TabItems의 가시성을 변경하려면 첨부 된 "Visibility"속성도 TabControl의 오작동을 방지합니다. 완전한 솔루션 :

public static class TabControlExtensions 
{ 
    /// <summary> 
    /// Use this property on a TabControl to correct the behavior 
    /// of selecting Collapsed TabItems. 
    /// </summary> 
    /// <param name="obj"></param> 
    /// <returns></returns> 
    public static bool GetSelectOnlyVisibleTabs(DependencyObject obj) 
    { 
     return (bool)obj.GetValue(SelectOnlyVisibleTabsProperty); 
    } 
    public static void SetSelectOnlyVisibleTabs(DependencyObject obj, bool value) 
    { 
     obj.SetValue(SelectOnlyVisibleTabsProperty, value); 
    } 
    public static readonly DependencyProperty SelectOnlyVisibleTabsProperty = 
     DependencyProperty.RegisterAttached("SelectOnlyVisibleTabs", typeof(bool), typeof(TabControlExtensions), new PropertyMetadata(false, SelectOnlyVisibleTabsChanged)); 
    public static void SelectOnlyVisibleTabsChanged(object sender, DependencyPropertyChangedEventArgs args) 
    { 
     var tabControl = sender as TabControl; 
     if (tabControl == null) return; 

     if ((bool)args.NewValue) 
     { 
      tabControl.SelectionChanged += TabControl_SelectionChanged; 
      CorrectSelection(tabControl); 
     } 
     else 
     { 
      tabControl.SelectionChanged -= TabControl_SelectionChanged; 
     } 
    } 

    private static void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs args) 
    { 
     var tabControl = sender as TabControl; 
     if (tabControl == null) return; 

     CorrectSelection(tabControl); 
    } 

    public static void CorrectSelection(TabControl tabControl) 
    { 
     var selected = tabControl.SelectedItem as UIElement; 
     if (selected == null) return; 

     // If the selected element is not suposed to be visible, 
     // selects the next visible element 
     if (selected.Visibility == System.Windows.Visibility.Collapsed) 
      tabControl.SelectedItem = tabControl.Items.OfType<UIElement>() 
       .Where(e => e.Visibility == System.Windows.Visibility.Visible) 
       .FirstOrDefault(); 
    } 
} 

public static class TabItemExtensions 
{ 
    /// <summary> 
    /// Use this property in a TabItem instead of the original "Visibility" to 
    /// correct the behavior of a TabControl when a TabItem's Visibility changes. 
    /// </summary> 
    /// <param name="obj"></param> 
    /// <returns></returns> 
    public static Visibility GetVisibility(DependencyObject obj) 
    { 
     return (Visibility)obj.GetValue(VisibilityProperty); 
    } 
    public static void SetVisibility(DependencyObject obj, Visibility value) 
    { 
     obj.SetValue(VisibilityProperty, value); 
    } 
    public static readonly DependencyProperty VisibilityProperty = 
     DependencyProperty.RegisterAttached("Visibility", typeof(Visibility), typeof(TabItemExtensions), new PropertyMetadata(Visibility.Visible, VisibilityChanged)); 

    public static void VisibilityChanged(object sender, DependencyPropertyChangedEventArgs args) 
    { 
     var tabItem = sender as TabItem; 
     if (tabItem == null) return; 

     var visibility = (Visibility)args.NewValue; 
     if (tabItem.Visibility == visibility) return; 

     tabItem.Visibility = visibility; 
     if (visibility == Visibility.Visible) return; 

     // Finds the tab's parent tabcontrol and corrects the selected item, 
     // if necessary. 
     var tabControl = tabItem.Ancestors().OfType<TabControl>().FirstOrDefault(); 
     if (tabControl == null) return; 

     TabControlExtensions.CorrectSelection(tabControl); 
    } 
} 

사용법 :

<sdk:TabControl local:TabControlExtensions.SelectOnlyVisibleTabs="True"> 
    <sdk:TabItem Header="tabItem1" Visibility="Collapsed"> 
     <TextBlock HorizontalAlignment="Center" 
        VerticalAlignment="Center" 
        Text="TabItem1 which should not be visible (1)" /> 
    </sdk:TabItem> 
    <sdk:TabItem Header="tabItem2"> 
     <TextBlock HorizontalAlignment="Center" 
        VerticalAlignment="Center" 
        Text="TabItem2 which should be visible (2)" /> 
    </sdk:TabItem> 
    <sdk:TabItem DataContext="{Binding ViewModel}" 
       Header="tabItem3" 
       local:TabItemExtensions.Visibility="{Binding MyProperty, 
                  Converter={StaticResource BoolToVisibilityConverter}}"> 
     <TextBlock HorizontalAlignment="Center" 
        VerticalAlignment="Center" 
        Text="TabItem with binded Visibility (3)" /> 
    </sdk:TabItem> 
</sdk:TabControl> 
관련 문제