2009-10-19 28 views
16

Có thể đặt một TabItem thành một XAML và tham khảo một cái gì đó riêng biệt như thế này:TabItem trong một XAML riêng

<TabControl> 
    <local:MyTabItem/> 
</TabControl> 



In Separate XAML: 
<UserControl x:Class="MyProject.MyTabItem" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <TabItem Header="MyTab"> 

    </TabItem> 
</UserControl> 

Tất nhiên nó không hoạt động, nhưng tôi đang tự hỏi làm thế nào tôi có thể làm điều này?

Trả lời

31

Nếu những gì bạn muốn làm chỉ đơn giản là làm cho mã dễ quản lý hơn thì tôi khuyên bạn nên xác định dữ liệu của mỗi tab trong điều khiển người dùng, nhưng vẫn có TabItem trong điều khiển tab chính.

Giả sử rằng mã ban đầu của bạn là thế này:

<TabControl> 
    <TabItem Header="Tab 1"> 
     <Grid> 
      <TextBlock Text="Tab Data" /> 
     </Grid> 
    </TabItem> 
</TabControl> 

Để làm cho mã dễ quản lý hơn bạn có thể phá vỡ các nội dung tab thành một UserControl như:

<UserControl x:Class="WpfApplication19.Tab1Data" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      > 
    <Grid> 
     <TextBlock Text="Tab Data" /> 
    </Grid> 
</UserControl> 

Và sau đó sử dụng người dùng kiểm soát trong TabControl của bạn như thế này:

<TabControl> 
     <TabItem Header="Tab 1"> 
      <tabData:Tab1Data /> 
     </TabItem> 
    </TabControl> 

Nếu bạn thực sự muốn bao gồm thứ e TabItem trong điều khiển người dùng của bạn sau đó bạn có thể làm điều đó bằng cách trước tiên tạo điều khiển người dùng và sau đó thay đổi loại điều khiển người dùng thành loại TabItem (đảm bảo bạn thay đổi điều này trong cả nút gốc xaml và mã phía sau).

này sẽ để lại cho bạn với một điều khiển tab đó trông như thế này:

<TabControl> 
     <tabData:TabItem1 /> 
     <tabData:TabItem2 /> 
     <tabData:TabItem3 /> 
    </TabControl> 

Và mỗi TabItem1 'User Control' sẽ loại TabItem. Dưới đây là một ví dụ:

<TabItem x:Class="WpfApplication19.TabItem1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Header="Tab 1" 
     > 
    <Grid> 
     <TextBlock Text="Tab Data" /> 
    </Grid> 
</TabItem> 

Và như tôi đã đề cập, hãy chắc chắn để thay đổi mã đằng sau để nó kéo dài TabItem thay vì sử dụng kiểm soát:

public partial class TabItem1 : TabItem 
{ 
    public TabItem1() 
    { 
     InitializeComponent(); 
    } 
} 
+0

Cảm ơn bạn rất nhiều. Nó hoạt động hoàn hảo như bạn thể hiện trong câu trả lời của bạn! –

+12

tabdata đến từ đâu? –

+0

Bạn nhận được thuộc tính 'xmlns' hoạt động như thế nào? Theo như tôi biết, nó đòi hỏi phải ở trong một hội đồng nước ngoài. –

2

Trên bề mặt, có vẻ như nó sẽ được giải quyết tốt nhất theo kiểu và/hoặc mẫu cho điều khiển TabItem mà bạn có thể lưu trữ trong một tệp tài nguyên riêng biệt. Bao nhiêu bạn cần để tùy chỉnh TabItem thực tế sẽ xác định nếu bạn chỉ có thể sử dụng một phong cách hoặc nếu bạn cần một mẫu.

Những gì bạn có thể làm là xác định một phong cách đặt tên cho mỗi TabItem trong một tập tin tài nguyên riêng biệt như vậy, tạo một MyResources.xaml mà trông giống như sau:

<ResourceDictionary> 
    <Style x:Key="MyTabItem" TargetType="{x:Type TabItem}"> 
     <!-- 
      you can just use simple property setters to set up 
      the TabItem or set the Template property to replace 
      entire tab look and feel 
     --> 
    </Style> 
</ResourceDictionary> 

Sau đó trong file App.xaml chính của bạn bạn hợp nhất trong từ điển tài nguyên:

<Application.Resources> 
    <ResourceDictionary> 
     <ResourceDictionary.MergedDictionaries> 
      <ResourceDictionary Source="MyResources.xaml"/> 
     </ResourceDictionary.MergedDictionaries> 
    </ResourceDictionary> 
</Application.Resources> 

Cuối cùng trong ứng dụng của bạn, bạn sẽ tận dụng những Styles bằng cách đơn giản thực hiện:

<TabItem Style="{DynamicResource MyTabItem}" /> 
+0

Xin lỗi, tôi cần phải xây dựng thêm. Tôi không đi sau khi tái sử dụng, nhưng làm cho mã của tôi dễ quản lý hơn. Ngay bây giờ tôi có tất cả XAML của tôi trong cửa sổ chính của tôi. Các mục lớn hơn được chứa trong một TabControl. Phá vỡ các TabItem có chứa một số điều khiển, sẽ làm cho nó dễ dàng hơn rất nhiều để đối phó với. Tôi chỉ là một người mới bắt đầu, vì vậy tôi không chắc chắn cách tiếp cận tốt nhất là gì. Tôi sẽ xem xét việc tạo mẫu cho TabItem. –

+1

Ok, sau đó tôi vẫn nghĩ rằng phong cách/mẫu phương pháp tiếp cận tôi đã đề xuất là một giải pháp tốt cho việc này. Tôi sẽ xây dựng trong câu trả lời của tôi. –

+0

-1 John Sheares đã yêu cầu cách tách các tệp XAML, không làm giảm mã dự phòng. –

1

Tôi nghĩ rằng những gì bạn muốn là để có được TabItem Nội dung khai báo riêng. Vì TabItem là một ContentControl, bạn có thể trình bày một UserControl làm nội dung của nó.

<TabControl> 
    <TabItem> 
     <local:YourTabContent1/> 
    </TabItem> 
    <TabItem> 
     <local:YourTabContent2/> 
    </TabItem> 
</TabControl> 

Trong XAML riêng:

<UserControl x:Class="MyProject.YourTabContent1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <......blah blah.../> 
</UserControl> 

Trong XAML khác bạn có thể có nội dung 2

<UserControl x:Class="MyProject.YourTabContent2" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <......blah blah.../> 
</UserControl> 
+0

Điều này cũng hoạt động. Một điều mà tôi nhận thấy là tôi phải xác định lại tài nguyên của mình một lần nữa bên trong nội dung tab XAML vì những thứ được xác định cho cửa sổ không có sẵn. Ngoài ra, làm cách nào để có được quyền kiểm soát ở một trong các tab từ mã cửa sổ phía sau có chứa TabControl? Tôi có sử dụng FindName() không? –

11

Câu trả lời trước đó từ Tony Borres đã bao gồm các khía cạnh quan trọng nhất. Nhưng nhận xét tiếp theo yêu cầu truy cập từ mã phía sau. Vì vậy, tôi cũng sẽ mở rộng ví dụ từ Tony để thể hiện khía cạnh này. Câu trả lời này cho thấy các không gian tên được yêu cầu. Tôi cũng đã thêm chúng vào câu trả lời từ Tony.

Để đơn giản làm cho mã dễ quản lý hơn, bạn nên xác định dữ liệu của từng tab trong điều khiển người dùng, nhưng vẫn có TabItem trong điều khiển tab chính. Chiến lược này hữu ích cho ví dụ để làm việc xung quanh FxCop CA1505: "Tránh mã không thể duy trì" khi sử dụng điều khiển tab với một số mục tab.

Giả sử rằng đây là mã gốc:

<Window x:Class="WpfApplication19.MainWindow" ...> 
    <TabControl> 
     <TabItem Header="Tab 1"> 
      <Grid> 
       <TextBlock Text="Data on Tab 1" Name="txtData1" /> 
      </Grid> 
     </TabItem> 
     <TabItem Header="Tab 2"> 
      <Grid> 
       <TextBlock Text="Data on Tab 2" Name="txtData2" /> 
      </Grid> 
     </TabItem> 
    </TabControl> 
</Window> 

Để làm cho mã dễ quản lý hơn các nội dung tab có thể được chuyển thành một UserControl như:

<UserControl x:Class="WpfApplication19.Tab1Data" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      Loaded="OnControlLoaded" 
      > 
    <Grid> 
     <TextBlock Text="Data on Tab 1" Name="txtData1" /> 
    </Grid> 
</UserControl> 

Và sau đó có thể sử dụng điều khiển người dùng mới trong TabControl như sau:

<Window x:Class="WpfApplication19.MainWindow" 
     xmlns:tabData="clr-namespace:WpfApplication19" ...> 
    <TabControl> 
     <TabItem Header="Tab 1"> 
      <tabData:Tab1Data x:Name="ucTab1Data" /> 
     </TabItem> 
     <TabItem Header="Tab 2"> 
      <Grid> 
       <TextBlock Text="Data on Tab 2" Name="txtData2"/> 
      </Grid> 
     </TabItem> 
    </TabControl> 
</Window> 

Bây giờ có thể để truy cập vào bộ râu trong của điều khiển người dùng từ cửa sổ chính và ngược lại. Xin lưu ý "x:" ở phía trước tên của người dùng.

public partial class MainWindow : Window 
{ 
    private void AccessWidgetWithinUserControl() 
    { 
     ucTab1Data.txtData1.Text = "New text on Tab 1"; 
    } 
} 

public partial class Tab1Data : UserControl 
{ 
    private MainWindow mainWindow = null; // Reference to the MainWindow 

    public Tab1Data() 
    { 
     InitializeComponent(); 
    } 

    // get a reference to main windows when it is available. 
    // The Loaded Event is set in the XAML code above. 
    private void OnControlLoaded(object sender, RoutedEventArgs e) 
    { 
     mainWindow = Window.GetWindow(this) as MainWindow; 
    } 

    private void AccessMainWindowsWidget() 
    { 
     mainWindow.txtData2.Text = "New text on Tab 2 in the main window"; 
    } 
} 

Mã được hiển thị để truy cập txtData2 sẽ giống nhau ngay cả khi được nhúng trong điều khiển người dùng riêng.

Các vấn đề liên quan