gpt4 book ai didi

wpf - 添加选项卡时,TabControl 的 SelectedItem 被 NewItemPlaceholder 覆盖

转载 作者:行者123 更新时间:2023-12-01 01:21:29 25 4
gpt4 key购买 nike

我正在开发一个 WPF TabControl,其最后一项始终是添加新选项卡的按钮,类似于 Firefox:
screenshot 1

TabControl 的 ItemSource 绑定(bind)到一个 ObservableCollection,通过这个“+”按钮向集合中添加一个项目非常有效。我遇到的唯一问题是,在单击“+”选项卡后,我无法将新创建的(或任何其他现有选项卡)设置为焦点,因此当添加选项卡时,用户界面看起来像这样:

screenshot 2

为了解释一下我是如何实现这种“特殊”选项卡行为的,TabControl 是模板化的,它的 NewButtonHeaderTemplate 有一个控件(在我的例子中是图像),它在 View 模型中调用 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 已绑定(bind)到它。它必须与 WPF 中更新的顺序有关,因为如果我在 SelectedListener 的 set 中设置断点我可以看到以下情况发生:
  • this.Listeners.Add(newListener);
  • this.SelectedListener = newListener;
  • 已选听众 set使用正确的 Listener 对象调用
  • 已选听众 set使用 NewItemPlaceholder 对象(根据调试器为 MS.Internal.NamedObject 类型)调用

  • 有没有办法可以解决这个问题?我有错误的方法吗?

    最佳答案

    我认为当您单击新选项卡时会触发两个事件:MouseLeftButtonDownTabControl.SelectionChanged
    我认为他们都在排队,然后一次处理一个。

    因此,您的项目被添加,设置为选中,然后在重新绘制之前发生 SelectionChanged 事件以将选择更改为 [+]标签。

    也许尝试使用 Dispatcher设置SelectedItem所以它发生在 TabControl 之后改变它的选择。或者,如果用户尝试切换到 NewTab,它会取消 SelectionChanged事件,因此所选选项卡实际上不会更改(当然,SelectedTab 将是您的 NewItem,因为会发生 MouseDown 事件)

    当我过去做这样的事情时,我实际上覆盖了 TabControl Template将 AddTab 按钮创建为 Button ,而不是 TabItem .我想建议这样做而不是使用 NewItemPlaceholder首先,但我从未尝试过使用 NewItemPlaceholder所以真的不知道它是否比覆盖 Template 更好或更差.

    关于wpf - 添加选项卡时,TabControl 的 SelectedItem 被 NewItemPlaceholder 覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8944314/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com