我工作的一個WPF TabControl的,其最後一個項目始終是一個按鈕添加新的選項卡,類似於Firefox時,覆蓋ObservableCollection,並通過此「+」按鈕將項目添加到集合中效果很好。我遇到的唯一問題是,點擊「+」選項卡後,我無法將新創建的(或任何其他現有選項卡)設置爲焦點,因此添加選項卡時,UI看起來是這樣的:的TabControl的的SelectedItem得到由NewItemPlaceholder添加標籤
要解釋一下我是如何實現這一「特殊」標籤的行爲,該TabControl的是模板及其NewButtonHeaderTemplate具有(在我的情況下,圖像)調用的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其中有效果,以更新的TabControl的的ItemSource和添加新的標籤:
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屬性不起作用,即使TabControl的的的SelectedItem綁定到它。它必須有一些做與哪些事情得到WPF更新的順序,因爲如果我設置一個斷點SelectedListener的set
我可以看到以下情況發生:
this.Listeners.Add(newListener);
this.SelectedListener = newListener;
- SelectedListener
set
使用正確的偵聽器對象調用 - SelectedListener
set
使用NewItemPlaceholder對象(根據調試器類型爲MS.Internal.NamedObject)調用
有沒有辦法解決這個問題?我有錯誤的方法嗎?
+1優秀的問題。有興趣聽到答案 –
你試過擴展TabControl來實現這個功能嗎? ..或者可能是附屬物? –
@jberger:我對WPF相當陌生,我真的不知道從哪裏開始。歡迎您在下面發佈解決方案。 – Fueled