2009-10-19 13 views
16

Czy to możliwe, aby umieścić TabItem w oddzielnym XAML i odniesienia coś takiego:TabItem w oddzielnym XAML

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

Oczywiście to nie działa, ale zastanawiam się, jak mogę to zrobić?

Odpowiedz

31

Jeśli chcesz, aby kod był łatwiejszy w zarządzaniu, zalecamy zdefiniowanie danych każdej karty w formancie użytkownika, ale nadal mam TabItem w kontrolce głównej.

Załóżmy, że oryginalny kod był następujący:

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

aby kod łatwiejsze można złamać zawartość zakładki do UserControl, takie jak:

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

a następnie użyć tego użytkownika kontroluj w TabControl w ten sposób:

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

Jeśli naprawdę chcesz włączyć e TabItem w kontroli użytkownika, możesz to zrobić, najpierw tworząc formant użytkownika, a następnie zmień typ kontrolki użytkownika na typ TabItem (upewnij się, że zmieniłeś to zarówno w głównym węźle xaml, jak i w kodzie).

To zostawiają cię z formantu karty, która wygląda tak:

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

i każdy TabItem1 "kontrola użytkownika będzie typu TabItem. Oto przykład:

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

I jak już wspomniałem, należy zmienić kod tyłu tak, że rozciąga TabItem zamiast kontroli użytkownika:

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

Dziękuję bardzo. Działa idealnie, jak pokazano w odpowiedzi! –

+12

tabdata pochodzi skąd? –

+0

Skąd się wzięła własność 'xmlns'? O ile mi wiadomo, wymaga to obcego zgromadzenia. –

2

Wygląda na to, że najlepiej byłoby rozwiązać za pomocą stylu i/lub szablonu kontrolki TabItem, którą można przechowywać w osobnym pliku zasobów. Ile trzeba dostosować rzeczywistego TabItem ustali, czy można po prostu użyć stylu lub, jeśli potrzebujesz szablonu.

Co można zrobić, to określić nazwany styl dla każdego TabItem w oddzielnym pliku zasobów tak jak utworzyć MyResources.xaml, który wygląda mniej więcej tak:

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

Następnie w głównym pliku App.xaml scalić w słowniku zasobów:

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

Wreszcie w aplikacji chcesz wykorzystać te style po prostu robi:

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

Przepraszam, powinienem był opracować więcej. Nie zamierzam ponownie używać, ale sprawić, by mój kod był łatwiejszy w zarządzaniu. Teraz mam wszystkie moje XAML w moim głównym oknie. Większe elementy są zawarte w TabControl. Łamanie TabItemów, które zawierają kilka kontrolek, ułatwiłoby obsługę. Jestem dopiero początkującym, więc nie jestem pewien, jakie jest najlepsze podejście. Zajmę się tworzeniem szablonu dla TabItem. –

+1

OK, to nadal uważam, że zaproponowane przeze mnie podejście do stylu/szablonu jest dobrym rozwiązaniem. Rozwiążę w mojej odpowiedzi. –

+0

-1 John Sheares pytał o sposób dzielenia plików XAML, a nie ograniczania nadmiarowego kodu. –

1

myślę co chciałeś jest dostać TabItem Treść deklarowana osobno. Ponieważ TabItem to ContentControl, możesz przedstawić UserControl jako jego treść.

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

w oddzielnych XAML:

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

W innym XAML można mieć zawartość 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

To też działa. Jedną z rzeczy, którą zauważyłem jest to, że muszę ponownie zdefiniować moje zasoby wewnątrz zawartości karty XAML, ponieważ te, które są zdefiniowane dla tego okna, nie są dostępne. Ponadto, w jaki sposób uzyskać kontrolę, która znajduje się na jednej z kart od strony kodu okna, która zawiera TabControl? Czy używam FindName()? –

11

poprzedniej odpowiedzi od Tony Borres obejmuje już najważniejsze aspekty. Dalszy komentarz wymaga jednak dostępu z kodu. Tak więc przedłożę przykład Tony'ego, aby pokazać ten aspekt również. Ta odpowiedź pokazuje wymagane przestrzenie nazw. Dodałem je również do odpowiedzi od Tony'ego.

Aby kod był łatwiejszy w zarządzaniu, zaleca się zdefiniowanie danych każdej karty w kontrolce użytkownika, ale nadal ma TabItem w głównym oknie kontrolnym. Ta strategia jest przydatna na przykład do obejścia FxCop CA1505: "Unikaj nieosiągalnego kodu", gdy używasz kontrolki tabulacji z kilkoma pozycjami tabulatora.

Załóżmy, że jest to oryginalny kod:

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

aby kod łatwiejsze zawartość zakładki mogą być przenoszone do UserControl, takie jak:

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

I wtedy jest możliwe użyj nowej kontrolki użytkownika w TabControl w ten sposób:

Teraz to możliwe aby uzyskać dostęp do wewnętrznych wigdetów kontrolki użytkownika z głównego okna i na odwrót. Zwróć uwagę na "x:" przed nazwą kontrolki użytkownika.

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"; 
    } 
} 

Pokazany kod dostępu do txtData2 byłby taki sam, nawet jeśli jest osadzony we własnej kontroli użytkownika.