2

У меня есть TabControl со многими привязками TabItems к ViewModel, который имеет свойства для каждой видимости TabItem.Silverlight TabItem Видимость не меняется

<sdk:TabControl> 
    <sdk:TabItem Name="Inventory" Header="Inventory" 
     Style="{StaticResource TabItemStyle}" 
     Visibility="{Binding Permissions.Inventory, 
     Converter={StaticResource PermissiveVisibilityConverter}, 
      ConverterParameter='Viewer'}" 
     DataContext="{Binding VM}" /> 

</sdk:TabControl> 

Все элементы TabItems по умолчанию имеют видимость свернуть. Но когда виртуальная машина изменяет TabItem на Visible, она не работает до тех пор, пока вы не нажмете мышь на элемент управления ...

Даже если я программным образом устанавливаю видимость с помощью кнопки, она ведет себя одинаково!

Я проверил, есть ли свойства виртуальной машины, уведомляющие пользовательский интерфейс, и они связаны с NotifyOnPropertyChanged. И если я привяжу данные к видимости кнопки, это будет просто отлично ... Это просто теги TabItems, которые, похоже, имеют ошибку.

Есть ли способ получить пользовательский интерфейс TabItem? Или обход для этого?

Спасибо!

+0

Какую версию SL вы используете? Измените свойство, измененное как на свойство Permissions, так и на свойство Inventory? –

+0

Silverlight 5. Да для обоих, и я проверил, обновляется ли ViewModel, если TabItem видит это изменение, и он делает это. Он просто не обновляет пользовательский интерфейс. – tcables

+0

Хммммм очень странно! Я знаю, что в Tab Control есть несколько ошибок, не глядя на меня, единственное, что я могу предложить, это загрузить исходный код инструментария из кода и попытаться выяснить, обрабатывает ли элемент управления вкладками внутреннюю видимость элементов табуляции? Извините, у меня нет простого ответа для вас. –

ответ

0

Что делать, если вы измените XAML, так что вы устанавливаете DataContext первый:

<sdk:TabItem Name="Inventory" Header="Inventory" 
    Style="{StaticResource TabItemStyle}" 
    DataContext="{Binding VM}" 
    Visibility="{Binding Permissions.Inventory, 
    Converter={StaticResource PermissiveVisibilityConverter}, 
     ConverterParameter='Viewer'}" /> 

Я предполагаю, что Permissions.Inventory это свойство на вашей модели представления, но так как вы не установите контекст в этот момент кажется, что привязка не должна работать.

Кроме того, ваш конвертер попадает, если вы установили точку останова, и если получатель на Разрешениях.

+0

Я поместил кнопку где-нибудь, и я установил ее, чтобы щелкнуть разрешение между свернутым и видимым, и, похоже, оно работает, не переставляя datacontext для установки в первую очередь. Проблема возникает только при инициализации формы. – tcables

+0

Если я инициализирую его как свернутый, а затем установите его как видимое с помощью кнопки, он не будет работать, пока вы не нажмете еще одну вкладку - тогда она появится видимой. Но в следующий раз, когда вы установили его, он рухнул, а затем снова виден, он отлично работает. – tcables

3

Я столкнулся с той же проблемой, и я смог ее преодолеть, используя прикрепленное свойство «Видимость», а не оригинальное. В этом новом свойстве я могу передать значение оригинальному свойству «Видимость», и в случае сглаживания элемента «SelectedItem» родительского вклада выберите следующий видимый элемент tabItem.

Однако, как указано here, этого может быть недостаточно, если первый элемент сбрасывается при загрузке TabControl. Этот случай должен был быть исправлен в самом TabControl, потому что тесты показали, когда поддельный «Visibility» установлен в первый раз, когда TabItem еще не имеет доступа к его TabControl. Из-за этого я также использовал прикрепленное свойство для 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> 
+0

Мне еще предстоит проверить это в моем проекте, но он кажется солидным. Спасибо за вашу работу :) – tcables

+0

Так что я просто использовал это, и проблема с ним просто не имела никакого эффекта. Небольшое изменение, которое мне нужно было сделать, это добавить обработчик событий для события Loaded TabControl. Пока все не загружено, не все свойства видимости еще не установлены. –

+0

Это работало благодаря усилиям. Но пришлось модифицировать Ancestors для GetSelfAndcestors в методе VisibilityChanged tabItem.GetSelfAndcestors(). OfType () .FirstOrDefault() – Ananda