Reputation: 493
All,
I have searched extensively for the solution here but I have a feeling my problem stems from a basic lack of knowledge about WPF. I am new to it and have thus far hacked and Googled my way through as best I can.
Basically, I have a Ribbon dynamically interacting with a TabControl. The Ribbon tabs select a category of items, the MenuItems in the RibbonGroups then choose an item within the category. Upon clicking an item, the tabs on the TabControl need to dynamically change. Whether that is just the Headers, the tabs themselves, or the entire TabControl is fine with me. Thus far, upon clicking a MenuItem on the inside one of the RibbonGroups, I attempt to just set the Header text equal to "blah" for each tab on the TabControl. Then the Header object throws a null pointer. This is what happens whether I set the Header, the Tabs, or the TabControl itself.
Why?!?!?!?
...and how in the world do I fix it???
Thanks!
Upvotes: 3
Views: 12363
Reputation: 1540
Try binding it to a list in the code like so:
private List<TabItem> TabItems = new List<TabItem>()
{
"Item1",
"Item2",
"Item3"
};
tabcontrol1.ItemSource = TabItems;
Then rebind it any time you want to change the items in the tabcontrol. This way you can dynamically change names and add more tab items. In doing this you'll have to programmatically add controls using the TabItem.Content property.
Upvotes: 0
Reputation: 6424
While RogerN's answer is probably a better answer, here is a code sample that changes the text that appears on a tab:
XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TabControl Name="MyTabControl">
<TabItem Header="Tab One">
<TextBlock Text="This is tab #1." />
</TabItem>
<TabItem Header="Tab Two">
<TextBlock Text="This is tab #2." />
</TabItem>
<TabItem Header="Tab Three">
<TextBlock Text="This is tab #3." />
</TabItem>
</TabControl>
<Button Grid.Row="1" Content="Change Tab" Name="ChangeButton" Click="ChangeButton_Click" />
</Grid>
Code behind:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void ChangeButton_Click(object sender, RoutedEventArgs e) {
((TabItem)MyTabControl.Items[0]).Header = "Changed!";
}
}
Upvotes: 1
Reputation: 3821
WPF is designed with data/UI separation in mind. One of the reasons you're having trouble finding a solution is because what you're trying to do is a no-no; instead of programmatically changing the UI's header text, you should be changing the underlying data instead, and allowing the WPF plumbing to update how the data is displayed.
A WPF tab control can literally contain any type of object; you could fill it with integers or strings or FooBars or whatever. There's no guarantee that any of these objects will define a Header property, and it's up to the developer to configure data bindings or templates which instruct the TabControl just how a FooBar or a whatever should be displayed.
In an ideal WPF application which adheres to the MVVM design pattern, you might have your TabControl bound to a collection of view models which each define a HeaderText property. Your view models would implement the INotifyPropertyChanged interface so that when the HeaderText property was changed on the view model then the UI would get updated.
Having said all that, if you've got an existing application it may be unrealistic to rewrite it from scratch using a different design pattern, and MVVM is not easily added on to an existing code base. If you're working with simple Designer generated UI without using any data binding, then the following code does what you ask. Sometimes.
foreach(TabItem item in tabControl.Items)
item.Header = "blah";
... but as I said before, there's no guarantee that a WPF TabControl's Items collection will contain items of type TabItem, so this code is not safe.
Upvotes: 5