Я работаю над WPF TabControl, последним элементом которого всегда является кнопка для добавления новой вкладки, похожая на Firefox:
![screenshot 1](https://i.stack.imgur.com/gcQqd.png)
ItemSource TabControl привязан к ObservableCollection, и добавление элемента в коллекцию с помощью этой кнопки «+» работает очень хорошо. Единственная проблема, с которой я сталкиваюсь, заключается в том, что после нажатия на вкладку «+» я не могу на всю жизнь установить вновь созданную (или любую другую существующую вкладку) фокусировку, и поэтому при добавлении вкладки пользовательский интерфейс выглядит так:
![screenshot 2](https://i.stack.imgur.com/UjLsD.png)
Чтобы объяснить немного, как я добиваюсь этого "особого" поведения вкладок, TabControl имеет шаблон, и его NewButtonHeaderTemplate имеет элемент управления (в моем случае Image), который вызывает команду AddListener в модели представления (только соответствующий код показано ниже):
<Window x:Class="AIS2.PortListener.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ais="http://www.leica-geosystems.com/xaml"
xmlns:l="clr-namespace:AIS2.PortListener"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
DataContext="{Binding Source={StaticResource Locator}>
<Window.Resources>
<ResourceDictionary>
<DataTemplate x:Key="newTabButtonHeaderTemplate">
<Grid>
<Image Source="..\Images\add.png" Height="16" Width="16">
</Image>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<cmd:EventToCommand
Command="{Binding Source={StaticResource Locator},
Path=PortListenerVM.AddListenerCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Grid>
</DataTemplate>
<DataTemplate x:Key="newTabButtonContentTemplate"/>
<DataTemplate x:Key="itemHeaderTemplate">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
<DataTemplate x:Key="itemContentTemplate">
<l:ListenerControl></l:ListenerControl>
</DataTemplate>
<l:ItemHeaderTemplateSelector x:Key="headerTemplateSelector"
NewButtonHeaderTemplate="{StaticResource newTabButtonHeaderTemplate}"
ItemHeaderTemplate="{StaticResource itemHeaderTemplate}"/>
<l:ItemContentTemplateSelector x:Key="contentTemplateSelector"
NewButtonContentTemplate="{StaticResource newTabButtonContentTemplate}"
ItemContentTemplate="{StaticResource itemContentTemplate}"/>
</ResourceDictionary>
</Window.Resources>
<TabControl Name="MainTab" Grid.Row="2" ItemsSource="{Binding Listeners}"
ItemTemplateSelector="{StaticResource headerTemplateSelector}"
ContentTemplateSelector="{StaticResource contentTemplateSelector}"
SelectedItem="{Binding SelectedListener}">
</TabControl>
Команда AddListener просто добавляет элемент в ObservableCollection, который имеет эффект для обновления ItemSource TabControl и добавления новой вкладки:
private ObservableCollection<Listener> _Listeners;
public ObservableCollection<Listener> Listeners
{
get { return _Listeners; }
}
private object _SelectedListener;
public object SelectedListener
{
get { return _SelectedListener; }
set
{
_SelectedListener = value;
OnPropertyChanged("SelectedListener");
}
}
public PortListenerViewModel()
{
// Place the "+" tab at the end of the tab control
var itemsView = (IEditableCollectionView)CollectionViewSource.GetDefaultView(_Listeners);
itemsView.NewItemPlaceholderPosition = NewItemPlaceholderPosition.AtEnd;
}
private RelayCommand _AddListenerCommand;
public RelayCommand AddListenerCommand
{
get
{
if (_AddListenerCommand == null)
_AddListenerCommand = new RelayCommand(param => this.AddListener());
return _AddListenerCommand;
}
}
public void AddListener()
{
var newListener = new TCPListener(0, "New listener");
this.Listeners.Add(newListener);
// The following two lines update the property, but the focus does not change
//this.SelectedListener = newListener;
//this.SelectedListener = this.Listeners[0];
}
Но установка свойства SelectedListener не работает, даже если к нему привязан SelectedItem объекта TabControl. Это должно быть как-то связано с порядком, в котором все обновляется в WPF, потому что, если я установлю точку останова в SelectedListener set
, я смогу увидеть следующее:
this.Listeners.Add(newListener);
this.SelectedListener = newListener;
- SelectedListener
set
вызывается с правильным объектом Listener
- SelectedListener
set
вызывается с объектом NewItemPlaceholder (типа MS.Internal.NamedObject согласно отладчику)
Есть ли способ, которым я могу обойти эту проблему? У меня неправильный подход?