Set WPF TabControl to show the same Content for every tab - wpf

I'd like to use a TabControl where each tab shows the same view just with different parameters. Therefore I do not want to create a new content control for each tab but reuse the same control for all tabs (binding some properties of it to the SelectedItem property of the TabControl)
I tried to my contained control as resource and set the Content property of the tab items to it, but this resulted in an exception, because the same element cannot appear as content in to different parents.
Any ideas?

<TabControl>
<TabControl.ContentTemplate>
<DataTemplate>
your view
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>

I found a solution in this question
TabControl's TabItems sharing same content... Do Not Want
(even if the poster wanted specifically the opposite behaviour :) ...)

Related

WPF ComboBox is not collapsing dropdown once it loses focus

I have a very strange situation. I have ComboBox which is loaded with some items. When I click on it, the drop-down expands showing all items.
If I now open another application such as Notepad, the dropdown will not collapse which I would expect to happen. As a result, any overlapping application, such as opened Notepad, will appear as being located in between the WPF hosting the ComboBox and the ComboBox drop-down like on screenshot below. Probably the z-order is somehow totally wrong.
I believe the reason for this behavior is the fact that the dropdown did not collapse at the first place. My ComboBox is part of a Usercontrol and its xaml is like:
<ComboBox ItemsSource="{Binding ValueSet}"
SelectedItem="{Binding SelectedNode}"
DisplayMemberPath="Name"
BorderBrush="Green"
BorderThickness="1" SelectionChanged="ComboBox_SelectionChanged">
</ComboBox>
In my opinion there is no any problem with the z-order in your xaml. The actual problem is in the ComboBox template in your application. You should find the actual style(or control template) your Combo is based on and check the Popup(usually named "PART_Popup") control inside that control template. The IsOpen property of the Popup should be bound to the ComboBox IsDropDownOpened property, like that:
`IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}"`
Any way you should search the solution for your problem in incorrect control template of the Combo control. There is something that make it be opened(probably by making the IsOpen property of the inner Popup control to be always true). Let me know if it you need more suggestion.

Showing UserControl once at the time with DataTemplateSelector

I have a couple specific user controls to Show some Content, e.g. simple like Image, WebControl but also two complex specific custom controls drawing on a canvas.
Now I thought using the DataTemplateSelector to handle the different UserControls. I actully used this http://tech.pro/tutorial/807/wpf-tutorial-how-to-use-a-datatemplateselector as a reference.
I changed the code so the form loads the UserControls dynamically (according to the file extension) in the following collection:
ObservableCollection<string> _pathCollection = new ObservableCollection<string>();
The only difference to the reference is now I want to navigate back and forward to the next control by showing one control only at the time. Which control should I use instead of ListView?
<Grid>
<ListView ScrollViewer.CanContentScroll="False"
ItemsSource="{Binding ElementName=This, Path=PathCollection}"
ItemTemplateSelector="{StaticResource imgStringTemplateSelector}">
</ListView>
</Grid>
How do I need to bind it to the template (equal to ItemTemplateSelector above)? WPF is still very new to me and I am learning.
Use a ContentControl. Bind your current item to the Content-property and the DataTemplateSelector to the ContentTemplateSelector-property.
<ContentControl Content="{Binding Path=CurrentItem, Mode=OneWay}", ContentTemplateSelector="{StaticResource imgStringTemplateSelector}" />
Your CurrentItem should be a DependencyProperty or a INotifyPropertyChanged-property of your DataContext. When you change your CurrentItem, the ContentControl will update the template automatically with help of your TemplateSelector.

MVVM - WPF Desktop

Just started learning MVVM. I have a tabcontrol where I am adding multiple instances of same views/pages
Dim tb As New UXTabItem
tb.Header = "Childrens"
tb.Name = "tab" & itrt
itrt = itrt + 1
tb.Source = New Uri("/Views/childrens.xaml", UriKind.Relative)
UXTabControl1.Items.Add(tb)
Since each of the same view will handle different data but since the uri is same so all the tabs get populated with same view and changes reflect on each tabs. Which should not be the case. Should I be using a separate viewmodel for each of those? Any example would be much helpful.
One of the primary goals/advantages of MVVM is that you don't create WPF UI objects in code.
You should be populating a collection of view model objects and binding the ItemsSource of the TabControl that you define in XAML to it. You should have a DataTemplate defined for the data type of those objects and put their XAML in there, instead of loading it at runtime.
The TabControl is a little tricky, because it uses two templates: the ItemTemplate is used to define the look of the tab, and the ContentTemplate is used to define the look of the tab items' content. It's pretty common to see this:
<TabControl ItemsSource="{Binding MyItems}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding}"/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
which populates the tab with a Text property on the view model, and the tab item's content with whatever template in the resource dictionary matches the view model's type.
I would have an ObservableCollection<TabViewModel> Tabs in my parent ViewModel, and bind the TabControl's ItemSource to that. Each Tab has it's own instance of TabViewModel, so adding a new Tab would mean adding a new TabViewModel to the Tabs collection in the ParentViewModel.
The TabViewModel would contain properties for things like Header or Uri, and these would be bound to the UI at the appropriate spots. Each TabViewModel can be drawn using the same View, but the data inside the object would be different for each tab.
My ParentViewModel would also contain a TabIndex property that defines which tab is selected
This is NOT trivial, IMO, and Rachel and Robert are both right.
Think of this task being one of managing 'work spaces", each represented by a tab control. I like to structure my view models into three related layers
DetailViewModel - the model for a given workspace (represented by a tab control)
MasterViewModel - the model for a collection of detail view models (ObservableCollection{DetailViewModel}). You would use this to bind to a list ion our presentation that shows what items may be selected for editing / display in a tab control. This is where filtering of the list would also be handled, if you allow that.
ShellViewModel - the model that actually has a collection of workspaces (ie, ObservableCollection{Workspace} along with the commands to manage them (ie, EditWorkspaceCommand, AddWorkspaceCommand, DeleteWorkspaceCommand). A workspace is a DetailViewModel that has a CloseCommand.
I found Josh Smith's MVVM article on MSDN useful for grokking this design.
HTH,
Berryl

Using expression blend to define the template of an item in a listbox. What am I doing wrong?

I am new to expression blend and defining some templates to my items in a WP7 page.
I have a listbox and I want to use EB to define the template of my items, the value (the text that should go in the listboxitem) is stored in a ObservableCollection which is itemsource of my listbox.
I opened my project in expression blend. I opened the page, selected the listbox and right-clicked, then I chose ItemTemplate (in another try I chose ItemContainerStyle). a new page appeared and I added a textbox to my template.
When I ran the project, in both cases (using ItemTemplate and ItemContainerStyle), I got a list with "TextBox" written, which is logic because of textbox I added to the template.
I imagine I have to change the TextBox's Text property to define a binding. But how can I define that the value used is stored in the Listbox.ItemSource property?
Thanks!
Just found it!
<TextBlock TextWrapping="Wrap" Text="{Binding}" TextAlignment="Center" FontWeight="Bold"/>
Text={Binding} solved my problem :)

Best practice for dynamically adding controls through copying existent controls in WPF

I have a TabControl.
While clicking a button I want to add a new TabItems to the TabControl.
Among various techniques I've chosen to create UserControl inside of a DockPanel.
Everything works fine, except for the location of control on a new TabItem is not 0 and it is
not expanded on the main form resize.
Everything is quite simple.
<TabItem Header="new control">
<DockPanel LastChildFill="True">
<tc:TabItemTemplate/>
</DockPanel>
</TabItem>
And TabItemTemplate is also located inside a DockPanel, but it's not docked inside a TabItem. What's the catch?
I would suggest using TabControl.ItemTemplate, and bind TabControl.ItemsSource to ObservableCollection of ViewModels. When user clicks on a button, add new View Model instance to the collection. Refer to this article for more details: WPF Apps With The Model-View-ViewModel Design Pattern

Resources