Reputation: 989
I'm using Prism with MEF and i want to dynamically add tab items to tab control w/o violating Prism - MVVM - MEF rules. can somebody show me in simple steps/example how to do this
Upvotes: 2
Views: 5550
Reputation: 3318
You need a region adapter for a TabControl. I made this for Ribbon Control so you can inspire from it :
public class RibbonRegionAdapter : RegionAdapterBase<Ribbon>
{
public RibbonRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory)
: base(regionBehaviorFactory)
{
}
protected override void Adapt(IRegion region, Ribbon regionTarget)
{
region.Views.CollectionChanged += (s, e) =>
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
foreach (RibbonTabItem RibbonTab in e.NewItems)
{
regionTarget.Tabs.Add(RibbonTab);
}
}
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
{
foreach (RibbonTabItem RibbonTab in e.OldItems)
{
regionTarget.Tabs.Remove(RibbonTab);
}
}
};
}
protected override IRegion CreateRegion()
{
return new AllActiveRegion();
}
}
in XAML: <Fluent:Ribbon prism:RegionManager.RegionName="{x:Static inf:RegionNames.RibbonRegion}"/>
to add a tab you need this :
IRegion RibbonRegion = _regionManager.Regions[RegionNames.RibbonRegion];
RibbonRegion.Add(YourTabItemView);
RegionNames is just a class in my infrastructe project :
public class RegionNames
{
public static string RibbonRegion = "RibbonRegion";
}
Hope that helps
Upvotes: 1
Reputation: 4538
First of all I am not saying my approach is the best of all possible approaches... but I just want to share it because I think it's cool :)
You can have TabControl region... so you can simply navigate to that region with some view :) ...what happens? When you navigate to TabControl region with some view... that view will be added as new TabItem.
Of course there are some things You have to do first.
You need to modify TabControl style. You just need to tell to TabControl where it can find Tab item's Header. You can add it to Application's resources of course.
So you need TabItemStyle... where you specify where is Header Text... something like this...
<Style x:Key="MyTabItemStyle" TargetType="{x:Type TabItem}">
<Setter Property="Header" Value="{Binding Content.DataContext.TabHeaderText, RelativeSource={RelativeSource Self}}"/>
...
And use it in default TabControlStyle
<Style TargetType="{x:Type TabControl}">
<Setter Property="ItemContainerStyle" Value="{StaticResource MyTabItemStyle}"/>
...
Now you can define TabControl region wherever you want. Note it should use that Style we defined earlier.
<TabControl Regions:RegionManager.RegionName="MyRegion" ... />
Well now you can navigate to that region with your view... Of course you will have to set DataContext of that view to some ViewModel with string property TabHeaderText...
Now it should work :) of course we are talking about Navigation so you should provide ViewModels with [RegionMemberLifetime(KeepAlive = true)]
attribute :) I hope it helps somebody some day.
Upvotes: 1
Reputation: 1333
A TabControl can be bound to a collection just like a number of other controls. Here's an example of a tabcontrol I have in a chat messaging program.
<TabControl ItemsSource="{Binding Path=Rooms, Mode=OneWay}" SelectedItem="{Binding Path=SelectedRoom, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=RoomName}" x:Name="Header" Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=DataContext}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
//in here is where you put controls for what you want the tabs to look like.
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
So in this example I have a collection of a custom datatype 'ChatRoom' called 'Rooms' which has properties on it like the RoomName. Whenever a user creates a new room it is added to the Rooms collection, and a new tabitem is created. So in my viewModel:
private ObservableCollection<ChatRoom> _Rooms;
public MainWindowViewModel()
{
this._Rooms = new ObservableCollection<ChatRoom>();
}
public ObservableCollection<ChatRoom> Rooms
{
get { return this._Rooms; }
}
Upvotes: 1