Hi,
I have a pretty basic need but unfortunately I couldn't figure out how to do it.
Below is the markup of my window which has a TabControl bound to TabList property
of it's DataContext:
<Window.Resources> <vm:MainWindowViewModel x:Key="ViewModel"/> <DataTemplate x:Key="DocumentItemTemplate" DataType="{x:Type ig:TabItemEx}"> <TextBlock Text="{Binding Path=Title}" Margin="3,0,0,0" /> </DataTemplate> <DataTemplate x:Key="DocumentContentTemplate"> <TextBlock Text="{Binding Path=Content}" Margin="3,0,0,0" /> </DataTemplate> </Window.Resources> <ig:XamTabControl Theme="Office2k7Black" x:Name="tcMain" DataContext="{StaticResource ViewModel}" ItemsSource="{Binding TabList}" SelectedIndex="0" ItemTemplate="{StaticResource DocumentItemTemplate}" ContentTemplate="{StaticResource DocumentContentTemplate}" AllowTabClosing="True" TabItemCloseButtonVisibility="WhenSelectedOrHotTracked"> </ig:XamTabControl>
Below is the code of ViewModel that is the DataContext of the window:
public class MainWindowViewModel { private ICommand _RemoveTabCommand; public MainWindowViewModel() { _RemoveTabCommand = new RelayCommand<TabClass>(RemoveTab, CanRemoveTab); TabList = TabClass.GetList(); } public ObservableCollection<TabClass> TabList { get; set; } public ICommand RemoveTabCommand { get { return _RemoveTabCommand; } } private bool CanRemoveTab(TabClass tab) { return tab != null; } private void RemoveTab(TabClass tab) { TabList.Remove(tab); } } public class TabClass { public string Title { get; set; } public string Content { get; set; } public TabClass(string title, string content) { Title = title; Content = content; } public static ObservableCollection<TabClass> GetList() { var result = new ObservableCollection<TabClass>(); result.Add(new TabClass("Tab 1", "Content 1")); result.Add(new TabClass("Tab 2", "Content 2")); result.Add(new TabClass("Tab 3", "Content 3")); result.Add(new TabClass("Tab 4", "Content 4")); result.Add(new TabClass("Tab 5", "Content 5")); result.Add(new TabClass("Tab 6", "Content 6")); return result; } }
What I want is to call the RemoveTabCommand when the close button of a TabItemEx is clicked.
This should be easy and straightforward but I couldn't do it. We use MEF and MVVM in our project
and our views exist as resources in a resource dictionary. Therefore we can't manipulate the view
controls in the code-behind; just bind our ViewModels to our Views manage everything through
commands.
Does anyone know how to do this?
Thanks in advance.
I just faced this problem en solved it by handling the Closed event of the TabItemEx class:
from this handler i could call a method an my viewmodel to remove the itemssource-instance from the collection (with the headername of the tab as key)
private void OnTabItemClosed(object sender, RoutedEventArgs e) { var tabitem = sender as TabItemEx; var context = DataContext as MainWindowViewModel; if (tabitem != null && context != null) { context.RemoveTabItem(tabitem.Header.ToString()); } }
hope this can help
No. A TwoWay binding is used to propogate changes to the property back to the source of the binding - e.g. to set the source property when the Text property of a TextBox is changed such as when you type. An ItemsControl would have no need to set its own ItemsSource property and it would mean nothing as it would be the same collection instance that you gave it. You may submit a suggestion to add a property in a future version such that when the associated collectionview is an IEditableCollectionView that the tab control try to remove the associated item when the close command is invoked.
Wouldn't a TwoWay binding to the ItemsSource remove the item from the bound collection?
Thanks!
Yes, you will need the whole style. In the style, you will find the close button declared with the following xaml :
<Button
Name="CloseButton"
Grid.Column="1"
Command="igWindows:TabItemExCommands.Close"
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
Visibility="{TemplateBinding ComputedCloseButtonVisibility}"
Style="{DynamicResource {x:Static igWindows:XamTabControl.CloseButtonStyleKey}}"
Margin="10,0,0,0"
/>
You will need to change the Command and bind it to your exposed command.