Why do we use itemsource actually? - c#

I am new to .net and i studied on msdn that it "represents a control that can be used to present a collection of items."
By this line what i understand is suppose if i use it for TabControl then it provides a control which will enable several TabItems (collection) to render on the given
conatiner.
<controls:TabControl Grid.Row="0" BorderThickness="0" Background="White"
ItemsSource="{Binding TabList, Mode=TwoWay, Converter={StaticResource TabConverter}}"
Could someone please correct (if i am wrong) with an example easy to understand showing why do we use it. What happen if we dont use it?

The purpose of the ItemsSource it so create a dynamic number of tabs depending on some data stored in a class (You need to set the DataContext of the Window though.
If you don't use ItemsSource, you could use separate TabItems to create a static number of tabs.
So it is this (showing a tab for each name in the list):
<TabControl ItemsSource="{Binding ListOfNames}}" />
Opposing to:
<TabControl>
<TabItem Header="John">
</TabItem>
<TabItem Header="Jane">
</TabItem>
<TabItem Header="Dave">
</TabItem>
</TabControl>

Related

WPF TabControl not firing Loaded event of unfocused children

I have a TabControl with a binding for the ItemsSource property. It's bound to a ObservableCollection. When I add an item to the collection, the tabs get created correctly, but only the first tab gets its Grid_Loaded event fired. I'm guessing this is because it's focused. I need to initialize stuff when a new tab opens, it contains a control that needs to be referenced.
<TabControl x:Name="tabSessions"
ItemsSource="{Binding Sessions}"
SelectedIndex="0"
BorderThickness="0"
Padding="0,0,0,0">
<TabControl.ItemTemplate>
<DataTemplate DataType="{x:Type vm:MyViewModel}">
<TextBlock Margin="4,4,16,4" Text="{Binding Name}"></TextBlock>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<Grid Loaded="Grid_Loaded">
<!-- View here -->
</Grid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
Is there an event that I could use to initialize this? I also need the DataContext to be set, and the view to be initialized.c#
The DataTemplate is reused by the tabs, which is why you're probably only seeing one Loaded event. It's only loaded the first time and then reused when you switch tabs. Only the binded content is changed.
Instead of listening to Loaded on the Grid, you could rather listen to DataContextChanged which will tell you every time the DataContext is set to a new object.
The DataContext will change when you switch tabs. The current tab will be set as the DataContext of the DataTemplate (and by extensions the Grid).
When using a DataTemplate you assume that the view is going to be the same, but the content is going to differ. If this is not the case and the views will differ based on the content, you'll probably want to look into using a DataTemplateSelector. This will let you define several DataTemplates and select one of them to use based on the current DataContext. You can read up on DataTemplateSelector in the Microsoft Docs

Dragablz TabablzControl Visibility property not working

I'm using dragablz:TabablzControl in a project of mine and I have the need of hide/show some tabs dinamically.
The fact is the control is not respecting the property Visibility of the TabItem.
I've tried with and without binding, like this:
<dragablz:TabablzControl Grid.Row="2" BorderThickness="0" FixedHeaderCount="20">
<TabItem Header="Additional Info" Visibility="{Binding ShowAdditionalInfoTab, Converter={StaticResource BooleanToVisibilityConverter}}">
<controls:AdditionalInfoControl />
</TabItem>
<TabItem Header="Additional Info" Visibility="Collapsed">
<controls:AdditionalInfoControl />
</TabItem>
</dragablz:TabablzControl>
But none is working. Change the "FixedHeaderCount" does not affect the result.
The tab remains always visible.
Is there any other way that I can achieve the result I need?
I've received a response from the development team, and I'm leaving it here for anyone who has the same problem.
Yeah, obviously there’s since changes to the standard tab control to support all of the extra features, and currently that’s not supported. You’d have to temporarily remove your hidden item from the source.

call to page inside tab control via code

I heed to create wizard and in the wizard I have tab control which have to call to the user control according to the context,I need to create the wizard which will able to invoke
different pages according to the user selection ,currently I call to the pages as follows which I think is not the right way,any Idea how should I do it via code (not in the xaml )i.e. according to some decision invoke the suitable page to the tab control.
this is the xaml:
<Border Grid.Column="1" Name="MainBorder">
<TabControl x:Name="MainTabControl" Height="638" VerticalAlignment="Bottom">
<TabItem Visibility="Collapsed" >
<Frame Source="page1.xaml" />
</TabItem>
<TabItem Visibility="Collapsed" >
<Frame Source="page2.xaml"/>
</TabItem>
<TabItem Visibility="Collapsed" Header="Step 3">
<TextBlock Text="Page 3"/>
</TabItem>
<TabItem Visibility="Collapsed" Header="Step 4">
<TextBlock Text="Page 4"/>
</TabItem>
</TabControl>
</Border>
UPDATE
I was tried in the main window like the following without success
create new tab by code and add to it the page 1 and then add it to the MainTabControl
TabControl tabControl = new TabControl(new Page1());
MainTabControl.add..
.
there is no add in the main tab control
For this scenario, I would use a Frame rather that tabs. The frame allows you to manage the flow of it's content via the NavigationService. You can use Uri's to display a page via the Frame.Source property, or a FrameworkElement via the Frame.Content property. Both are DependencyProperties and can therefore be bound to.
Paul Stovel wrote an excellent blog on this called WPF Navigation. Everything you need to create a wizard from a frame can be found in this blog, including passing values between pages and templating of the Frame to simply handle the display of navigation buttons.
I would agree with Mark, it is a lot easier to use NavigationWindows than TabControls.
I've worked on a lot of interfaces like this and written up some of the basic things with,
WPF Wizards, Part 1
WPF Wizards, Part 2
Then more recently I worked out how to get the styling just right
Styling Wizards
In fact I've released the styling and examples as open source at
WinChrome
There is some simple example code including use of a navigation list to the left with,
WinChrome.Win7Demo
Hope this helps

Accessing a list picker inside a PanoramaHeader Template

I have a panorama control in which I have create a header template to add a list picker inside it. (Just like the peoples hub to select social accounts)
<DataTemplate x:Key="PanoramaItemHeaderTemplate">
<ContentPresenter>
<StackPanel Height="129">
<TextBlock Text="{Binding}" FontSize="72" Margin="0,7,0,0" />
<toolkit:ListPicker x:Name="listPick" Margin="0,-21,0,0" BorderThickness="0">
<toolkit:ListPickerItem Content="twitter"></toolkit:ListPickerItem>
</toolkit:ListPicker>
</StackPanel>
</ContentPresenter>
</DataTemplate>
The panorama control is inside the MainPage.xaml file and I want to have access to the listpicker from the code behind to be able to populate it, and handle it selection events.
I don't know how to do this. I tried adding the x:name property to the list picker I don't have access to it in the MainPage code behind.
Any idea on how to approach this is very welcomed, thanks!
From what you have now, the quickest way to do what you want is to traverse the visual tree
See here for the implementation:
How to access a specific item in a Listbox with DataTemplate?
You cannot access the ListPicker by x:Name because it is not unambiguous: there is a ListPicker generated for each PanoramaItem in your Panorama. So the first question is, is it really the think you want to do? If so you need to populate it using a binding (ItemSource)
You can access an element inside another resource, consider this example:
<Grid Name="myGrid">
<StackPanel x:Name="stack1">
<TextBlock x:Name="abc"/>
</StackPanel>
</Grid>
We can only access the Grid myGrid in code by default. To get reference to the StackPanel we can do this:
StackPanel myStack=myGrid.FindName("stack1") as Stackpanel;
After that we can get reference to the TextBlock:
TextBlock myTextBlock=myStack.FindName("abc") as TextBlock;
You can modify myTextBlock after that as you may like. You can apply the same technique in your case and it will work.
Hope that helps :).

Binding one collection to multiple tabs with filters

In my small WPF project, I have a TabControl with three tabs. On each tab is a ListBox. This project keeps track of groceries we need to buy. (No, it's not homework, it's for my wife.) So I have a list of ShoppingListItems, each of which has a Name and a Needed property: true when we need the item, and false after we buy it.
So the three tabs are All, Bought, and Needed. They should all point to the same ShoppingListItemCollection (which inherits from ObservableCollection<ShoppingListItem>). But Bought should only show the items where Needed is false, and Needed should only show items where Needed is true. (The All tab has checkboxes on the items.)
This doesn't seem that hard, but after a couple hours, I'm no closer to figuring this out. It seems like a CollectionView or CollectionViewSource is what I need, but I can't get anything to happen; I check and uncheck the boxes on the All tab, and the items on the other two tabs just sit there staring at me.
Any ideas?
You can use a CollectionViewSource to reuse the original collection with a filter.
<Window.Resources>
<CollectionViewSource x:Key="NeededItems" Source="{Binding Items}" Filter="NeededCollectionViewSource_Filter" />
<CollectionViewSource x:Key="BoughtItems" Source="{Binding Items}" Filter="BoughtCollectionViewSource_Filter" />
</Window.Resources>
<TabControl>
<TabItem Header="All">
<ListBox DisplayMemberPath="Name" ItemsSource="{Binding Items}" />
</TabItem>
<TabItem Header="Bought">
<ListBox DisplayMemberPath="Name" ItemsSource="{Binding Source={StaticResource BoughtItems}}" />
</TabItem>
<TabItem Header="Needed">
<ListBox DisplayMemberPath="Name" ItemsSource="{Binding Source={StaticResource NeededItems}}" />
</TabItem>
</TabControl>
Some code behind is required for the filter.
private void NeededCollectionViewSource_Filter(object sender, FilterEventArgs e)
{
e.Accepted = ((ShoppingListItem) e.Item).Needed;
}
private void BoughtCollectionViewSource_Filter(object sender, FilterEventArgs e)
{
e.Accepted = !((ShoppingListItem) e.Item).Needed;
}
Here are a couple of ideas:
When tabs Bought and Needed load, filter them yourself by creating new collections with the items you want, or
when tabs Bought and Needed load, override the list item databind and toggle visability based on Needed

Categories

Resources