You can access the controls by walking the visual tree using Content
, Children
or other properties.
TabItem tab2 = TrycloneElement(TabItem1);
var grid = (Grid) tab2.Content;
var label1 = (Label) grid.Children[0];
var label2 = (Label) grid.Children[1];
var button = (Button) grid.Children[2];
An alternative is to use the VisualTreeHelper
and convenience helper methods like described here:
Now, these methods work, but you do not need them. You are actually trying to reinvent the wheel. Reusing the same visual structure with different data can be achieved with data templating in a convenient way.
You can use the same technique for your TabControl
. I will show you a quick conceptual example that would even comply with the MVVM pattern. This example is not complete. It serves as a base for you to learn about an alternative to your current approach. You can of course also make this approach work in code-behind with a few modifications.
Create a data class like below with your application information. Here I assume that it is not editable, otherwise you need to implement INotifyPropertyChanged
in order to update the user interface on changes.
public class AppInfo
{
public AppInfo(string name, string description)
{
Name = name;
Description = description;
}
public string Name { get; }
public string Description { get; }
}
Expose a list of AppInfo
(or an ObservableCollection
if the collection is changed at runtime).
public List<AppInfo> AppInfos { get; }
Initialize the list appropriately and add your items, for example:
AppInfos = new List<AppInfo>
{
new AppInfo("Visual Studio", "A popular IDE."),
new AppInfo("Calculator", "Does the math for you."),
new AppInfo("Chrome", "A web browser.")
};
The tab control would bind its ItemsSource
to the AppInfos
.
<TabControl ItemsSource="{Binding AppInfos}">
In order to create a reusable visual representation, create a DataTemplate
as ItemTemplate
(this is the tab header) and a ContentTemplate
(this is the tab content).
<TabControl ItemsSource="{Binding AppInfos}">
<TabControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:AppInfo}">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate DataType="{x:Type local:AppInfo}">
<Grid>
<Label Content="{Binding Name}"
HorizontalAlignment="Left"
Margin="10,10,0,0"
VerticalAlignment="Top"
FontSize="18"/>
<Label Content="{Binding Description}"
HorizontalAlignment="Left"
Margin="11,44,0,0"
VerticalAlignment="Top"
FontSize="18"/>
<Button Content="Show Open Dialog"
IsEnabled="True"
HorizontalAlignment="Left"
Margin="11,185,0,0"
VerticalAlignment="Top" Width="194"
Command="{Binding DataContext.OpenCommand, RelativeSource={RelativeSource AncestorType={x:Type TabControl}}}"
CommandParameter="{Binding}"/>
</Grid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
Now, both templates are reused for each item in the AppInfos
collection. The data template uses bindings to the corresponding properties, which automatically pick up the values for each item.
The Button
is special here, since it can be clicked to execute an action. This action is probably the same for all items, except that it needs a concrete item to work with. You can encapsulate this logic in commands.
This is another important aspect that can make your life easier, but is beyond the scope of this question. There are lots of tutorials out there. You could expose another property:
public ICommand OpenCommand{ get; }
The button in XAML binds its Command
to this property (RelativeSource
is needed to get the right data context for binding). The CommandParameter
will pass the current AppInfo
item to the command. In code, you could then execute your custom logic on this item. No need to know about user interface elements, only data.
Disclaimer: I know that this is pretty overwhelming. That is why I provided an immediate (dirty) solution to your issue and an example with links to resources to gradually learn a better way with concrete samples for your exact problem. Once you get used to MVVM, data binding and data templating, you will see how much easier more complex issues can be solved and what the benefits are in terms of maintainability and reuseability.