Reputation: 2093
I am having difficulty trying to get a very simple scenario working with PRISM 2.0 for WPF. I want the main workarea of my application to be a TabControl
. Each time I add a view, I want it to appear as a TabItem
on the TabControl
.
Sounds easy right?
My region, which is in my Shell.XAML looks like this:
<Controls:TabControl
Name="MainRegion"
cal:RegionManager.RegionName="{x:Static Infrastructure:RegionNames.TabRegion}"
ItemContainerStyle="{StaticResource ShellTabItemStyle}" />
The style: ShellTabItemStyle
looks like this:
<Style x:Key="ShellTabItemStyle" TargetType="{x:Type TabItem}">
<Setter Property="Header" Value="{Binding Content.DataContext.HeaderInfo, RelativeSource={RelativeSource Self}}" />
</Style>
This should set the Header
of the TabItem
to the HeaderInfo
property on the DataContext
of the view. (I got this idea from this article) The DataContext
of my view is a very simple Presenter
which has a HeaderInfo
property on it:
public string HeaderInfo = "The Header Text";
My view is a simple WPF usercontrol and looks like this:
<StackPanel>
<TextBox Text="Hello World" Name="MyTextBox"></TextBox>
<Image Source="..SomeImage.PNG" Name="MyImage"></Image>
</StackPanel>
So far, so good. If I add the view to the region I get a tab control and I get a tab with the text set to "The Header Text". My problem is that there is absolutely no content appearing on the tab. My view contains a simple Image
and a TextBox
, but neither of them show up in the TabItem
. If I break out Snoop and look around, there isn't an image in sight.
What am I missing here - is there an easier way?
Upvotes: 4
Views: 6724
Reputation: 9500
Some random thoughts:
Upvotes: 0
Reputation: 2093
I was unable to get any of the suggested answers to work. Extensive googling didn't help either. I gave the problem some thought over the weekend and more I thought about it, the more it occured to me that there is a bit of a code smell about this approach. You inject a view into your Tab Region... some magic stuff happens and a tab gets added... you have to add some imcomprehensible dynamic binding to some XAML styling stored in a file somewhere and this may or may not set your header text. If any one single element of this is just a little bit wrong you won't get an error but it just won't work.
In my view this is both brittle (i.e. very easy to break) and pretty inpenetrable unless you have a deep understanding PRISM, the model, and of XAML. Fortunately there is a much nicer and simpler way to do this:
Simply create a view called TabRegionView which contains only a blank TabControl. You probably want to add this to your Shell.xaml. Create an Event called InjectTabView which has a Payload of type UserControl and subscribe to this event in your TabRegionView control. When the event fires in TabRegionView, you create the TabItem manually and add the view to the TabItem like so:
public void TabAdded(UserControl view)
{
var item = new TabItem();
item.Content = view;
item.IsSelected = true;
item.Header = "Header Text";
mainTab.Items.Add(item);
}
When you want to display a view as a new tab, your code looks something like this:
var view = new View(params);
_eventAggregator.GetEvent<InjectTabViewEvent>()
.Publish(view);
This will be picked up by TabRegionView and the view will be added as a new tab. You could easily wrap the View in harness of some type that contains header text, an image and bool to indicate whether or not the tab should be autoselected.
IMHO this technique has the dual advantages of giving you direct control of what is going on AND it is much easier to follow.
I'd be very interested to get an opinion on this from any PRISM officianados.
Upvotes: 3
Reputation: 25650
If you are using RegionManager, you need to Activate your view. There's likely some piece of code where you are adding the view to the region, you just additionally need to tell that region to activate it.
public void AddViewToRegion(IRegion region, object view)
{
region.Add(view);
region.Activate(view);
}
It seems silly, but you get the behavior you are seeing if you don't do this. I found this kinda frustrating, but it was easy enough to fix. The behavior is even stranger when you add multiple tabs if you don't at least Activate the first view you add.
My understanding is that if you don't do this, the view never becomes part of the visual tree (this is a side-effect of the fact that the TabControl deactivates (removes from the visual tree) when a tab isn't "in front". This is good for certain operations, but makes things like this be a little wonky.
Upvotes: 2