2010-05-03 17 views
6

Tôi đang xây dựng một ứng dụng LOB có một phần chính và một TabControl với các TabItem khác nhau trong đó. Khi nhấn lưu ý tưởng là bất kỳ trường nào bị lỗi đều được đánh dấu và trường đầu tiên bị lỗi sẽ lấy tiêu điểm.Silverlight TabControl - Tìm và chọn một TabItem từ một Điều khiển đã cho trong TabItem

Nếu trường đầu tiên và duy nhất có lỗi nằm trên tab Chưa được chọn, tab này sau đó sẽ được chọn và trường có lỗi sẽ được đánh dấu và có tiêu điểm. Nhưng tôi không thể làm được điều này.

Điều gì dường như đang xảy ra là tab Không được chọn không nằm trong cây trực quan, do đó bạn không thể điều hướng trở lại TabItem đang sở hữu và biến TabItem hiện đang được chọn trong TabControl.

Có ai có ý tưởng về cách thực hiện điều này có thể đạt được không?

Trả lời

1

Cách tôi giải quyết nó (bằng cách hỏi Kiến trúc sư trưởng) ...

Tạo giao diện ITabKích hoạt với một phương pháp Kích hoạt.

Tạo lớp học có nguồn gốc từ Grid và ITabActivator được gọi là TabPageActivator. Các nhà xây dựng trong đó có TabITem và TabControl.

Thay vì thêm một lưới đơn giản vào TabItem.Contents, hãy thêm một TabPageActivator.

Thay đổi phát hiện Gốc để sử dụng ...

DependencyObject parent = _Control.Parent;

... thay vì sử dụng VisualTreeHelper.

Vì vậy, khi bạn điều hướng các thử nghiệm Hierarchy cho ...

if (mẹ là TabActivator) (cha mẹ như ITabActivator) .Activate()

... nên khi Activate được gọi là

m_TabControl.SelectedItem = m_TabItem; // Từ Tham số Constructor.

... và đừng quên bạn có thể có các tab lồng nhau, do đó bạn cần tiếp tục đi lên Hệ thống phân cấp.

+0

Chắc chắn bạn thấy mọi tab được chọn trước, trước khi tab xác nhận cuối cùng của bạn hiển thị? –

+0

Không, nó hoạt động tốt. Tôi có thể hơi ngắn trong lời giải thích của tôi về giải pháp. Tôi có thể giải thích chi tiết hơn nếu bạn muốn? –

+0

nitpick nhỏ: Tôi tìm thấy nó là một ý tưởng thực sự xấu để sử dụng nhà thầu không mặc định trên điều khiển. Nó làm cho kiểm soát không xaml thân thiện ... – TDaver

0

Tôi biết một cách, nhưng nó là xấu xí. Nó liên quan đến việc sử dụng DispatcherTimer với khoảng thời gian vài phần nghìn giây. Trong Page_Loaded, bạn sẽ bắt đầu hẹn giờ. Sau đó, trên mỗi đánh dấu nó đặt IsSelected = true cho một trong các mục tab. Trong lần đánh dấu tiếp theo, chọn mục tab tiếp theo, v.v. cho đến khi tất cả các tab đã được chọn. Sau đó, bạn sẽ phải chọn mục đầu tiên một lần nữa và giết bộ hẹn giờ. Điều này sẽ buộc các hình ảnh trong các mục tab để tải.

Bạn cũng sẽ phải che tabControl bằng đường viền hoặc một thứ gì đó trong quá trình thao tác này. Nếu không, người dùng sẽ thấy tất cả các mục tab nhanh chóng lướt qua.

+0

Vâng - không phải là một giải pháp khá. –

+0

Đúng. Tôi sử dụng giải pháp này bản thân mình, và nó làm cho tôi cringe mỗi khi tôi nhìn vào mã. :) Nếu tôi đã làm điều đó một lần nữa tôi sẽ đóng gói nó trong một hành vi để có được nó ra khỏi tầm nhìn. Thật không may tôi không thể nghĩ ra một cách khác để làm cho hình ảnh render. –

1

Tôi sử dụng TabControls để điều hướng trên một trong các trang web của tôi (YinYangMoney) và xây dựng một vài phương pháp tiện ích giúp tôi chọn các tab bằng cách sử dụng tên thẻ. Dưới đây là các đoạn mã nên hoạt động cho bạn.

Các Extensions lớp:

using System; 
using System.Linq; 
using System.Windows.Controls; 

namespace MyApplication 
{ 
    internal static class Extensions 
    { 
     // Extension for TabControl 
     internal static void SelectTab(this TabControl tabControl, this TabItem tabItem) 
     { 
      if (tabControl == null || tabItem == null) 
       return null; 

      SelectTab(tabControl, tabItem.Tag); 
     } 

     // Extension for TabControl 
     internal static void SelectTab(this TabControl tabControl, string tabTagName) 
     { 
      if (tabControl == null) 
       return null; 

      // Find the TabItem by its Tag name 
      TabItem mainTabItem = tabControl.FindByTag(tabTagName); 
      if (mainTabItem == null) 
       return; 

      // Check to see if the tab needs to be selected 
      if (tabControl.SelectedItem != mainTabItem) 
       tabControl.SelectedItem = mainTabItem; 
     } 

     // Extension for TabControl 
     internal static TabItem FindByTag(this TabControl tabControl, string tagFragment) 
     { 
      if (tabControl == null || tagFragment == null) 
       return null; 

      return tabControl.Items 
        .OfType<TabItem>() 
        .Where(item => item.Tag != null && item.Tag.ToString().StartsWithIgnoreCase(tagFragment)) 
        .FirstOrDefault(); 
     } 

     // Extension for string 
     internal static bool StartsWithIgnoreCase(this string source, string target) 
     { 
      return source.StartsWith(target, StringComparison.CurrentCultureIgnoreCase); 
     } 
    } 
} 

Các XAML cho TabControl và TabItems của bạn sẽ trông như thế này:

<Controls:TabControl x:Name="x_TabControl"> 
    <Controls:TabItem Header="Welcome" Tag="/Home/Welcome" x:Name="x_WelcomeTab" /> 
    <Controls:TabItem Header="FAQ" Tag="/Home/FAQ" /> 
    <Controls:TabItem Header="Contact Us" Tag="/Home/Contact_Us" /> 
    <Controls:TabItem Header="Privacy Policy" Tag="/Home/Privacy_Policy" /> 
    <Controls:TabItem Header="My Account" Tag="/Home/My_Account" /> 
</Controls:TabControl> 

Và bạn có thể chọn TabItem Chào mừng như vậy:

x_TabControl.SelectTab("/Home/Welcome"); 

hoặc

x_TabControl.SelectTab(x_WelcomeTab); 
+0

Vấn đề là tìm TabItem được chọn dựa trên một điều khiển sẽ được hiển thị bên trong nó. –

4

Để nạp TabItem:

tabControl.SelectedItem = tabItemOfInterest; 
tabControl.UpdateLayout(); 

Điều này làm cho tabItemOfInterest để tải alongwith tất cả các điều khiển chứa trong TabItem.

Dòng dưới đây một mình không tải tabItemOfInterest:

tabControl.SelectedItem = tabItemOfInterest; 

Tôi sẽ, tuy nhiên, rất quan tâm đến cách tiếp cận David áp dụng để có được sự kiểm soát sai lầm.

1

Giải pháp của tôi bằng thuộc tính đính kèm TabItem. Tạo lớp TabItemExtender:

/// <summary> 
/// TabItem Extender class with TabItem property 
/// </summary> 
public class TabItemExtender 
{ 
    #region property getters/setters 
    /// <summary> 
    /// TabItem attached dependency property 
    /// </summary> 
    public static readonly DependencyProperty TabItemProperty = DependencyProperty.RegisterAttached("TabItem", typeof(TabItem), typeof(TabItemExtender), null); 

    /// <summary> 
    /// TabItem Property getter 
    /// </summary> 
    public static TabItem GetNavigateUri(DependencyObject source) 
    { 
     return (TabItem)source.GetValue(TabItemExtender.TabItemProperty); 
    } 

    /// <summary> 
    /// TabItem Property setter 
    /// </summary> 
    public static void SetNavigateUri(DependencyObject target, TabItem value) 
    { 
     target.SetValue(TabItemExtender.TabItemProperty, value); 
    } 
    #endregion 
} 

Tiếp theo làm điều này trên TabControl kiện tải:

private void ExtendedTabControl_Loaded(object sender, System.Windows.RoutedEventArgs e) 
{ 
    foreach (object item in this.Items) 
    { 
     var tabItem = item as TabItem; 
     if (tabItem != null && tabItem.Content != null) 
     { 
      var element = (FrameworkElement)tabItem.Content; 
      element.SetValue(TabItemExtender.TabItemProperty, tabItem); 
     } 
    } 
} 

và điều này trước khi thiết lập trọng tâm:

var element = (UIElement)control; 
while (element != null) 
{ 
    //Get TabItem 
    var tabItem = (TabItem)element.GetValue(TabItemExtender.TabItemProperty); 

    if (tabItem != null) 
    { 
     if (!tabItem.IsSelected && tabItem.IsEnabled) 
     { 
      tabItem.IsSelected = true; 
      ((TabControl)tabItem.Parent).UpdateLayout(); 
     } 

     break; 
    } 

    element = (UIElement)VisualTreeHelper.GetParent(element); 
} 

control.Focus();