我正在使用MVVM模式使用C#和WPF创建一个简单的应用程序。有一个带有几个按钮的主窗口和一个包含视图模型列表的ContentControl,其中一个是SearchViewModel。按钮在视图模型之间翻转。
SearchViewModel绑定到SearchView并包含TabControl。 ItemsSource属性绑定到SearchTabViewModel列表。在SearchViewModel的构造函数中,我正在初始化SearchTabViewModels的ObservableCollection,然后添加两个选项卡。第一个标签有" +"对于它的标题,另一个是普通的搜索标签。 TabControl的SelectionChanged事件绑定到一个方法,该方法检查" +"单击选项卡。如果是,则在" +"之前插入新选项卡。选项卡和TabControl的SelectedIndex属性设置为插入选项卡的索引。相当简单的设置。
我遇到的问题是,首次运行应用程序时,您可以点击" +"选项卡并插入一个新选项卡,然后选择" +"选项卡已经死了,单击它时没有任何反应。 SelectionChanged事件不会触发。我已经检查过,并且SelectedIndex被设置为之前的标签,因此它不是所选标签。要修复它,你必须先点击另一个标签,然后一切正常。它只是在开始时冻结了一次。
有人能看出问题所在吗?我包括代码的相关部分:
XAML
<TabControl
Name="searchTabControl" ItemsSource="{Binding Path=SearchTabs}"
SelectedIndex="{Binding Path=SelectedTabIndex}"
ItemTemplateSelector="{Binding Source={StaticResource searchTabTemplateSelector}}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged" >
<i:InvokeCommandAction
CommandName="searchTabHasChanged" Command="{Binding SelectionChangedCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=CommandName}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
....more code
SearchViewModel
public class SearchViewModel : ObservableObject, IPageViewModel
{
#region Fields
public ObservableCollection<SearchTabViewModel> SearchTabs { get; set; }
private int _selectedTabIndex;
private ICommand _selectionChangedCommand;
#endregion
public SearchViewModel()
{
try
{
// initialize the SearchTabs array
this.SearchTabs = new ObservableCollection<SearchTabViewModel>();
// add a tabItem with + in header
SearchTabViewModel tabAdd = new SearchTabViewModel("+");
this.SearchTabs.Add(tabAdd);
// add first tab
AddTabItem();
SelectedTabIndex = 0;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
#region Properties/Commands
public int SelectedTabIndex
{
get { return _selectedTabIndex; }
set
{
_selectedTabIndex = value;
OnPropertyChanged("SelectedTabIndex");
}
}
public ICommand SelectionChangedCommand
{
get
{
if (_selectionChangedCommand == null)
{
_selectionChangedCommand = new RelayCommand(
param => TabSelectionChanged(param)
);
}
return _selectionChangedCommand;
}
}
#endregion
#region Methods
public void TabSelectionChanged(Object source)
{
if (source.ToString() == "searchTabHasChanged")
{
SearchTabViewModel tab = this.SearchTabs[SelectedTabIndex];
if (tab != null && tab.Header != null)
{
if (tab.Header.Equals("+"))
{
// add new tab
SearchTabViewModel addedTab = AddTabItem();
// select newly added tab item
SelectedTabIndex = this.SearchTabs.IndexOf(addedTab);
}
}
}
}
private SearchTabViewModel AddTabItem()
{
int count = SearchTabs.Count;
// create new tab item
SearchTabViewModel tab = new SearchTabViewModel();
tab.Header = string.Format("Tab {0}", count);
// insert tab item right before the last (+) tab item
this.SearchTabs.Insert(count - 1, tab);
return tab;
}
#endregion
}
此外,我注意到的另一个奇怪的行为是,当您第一次运行应用程序并单击&#34; +&#34;标签一次添加新标签和&#34; +&#34;选项卡死亡,如果应用程序失去焦点并再次获得焦点,则会触发SelectionChanged事件并添加新选项卡?这种行为只发生在&#34; +&#34;标签已经死了。通过单击另一个选项卡修复它后,此行为将消失。
答案 0 :(得分:1)
在TabSelectionChanged中,添加一个新的TabItem并相互更改SelectedTabIndex。问题是尚未触发在视图中生成新TabItem的ItemContainerGenerator。这是在DataBinding阶段完成的。因此,当您设置SelectedTabIndex时,实际上将其设置为(已选中)+选项卡。
要解决此问题,请通过调度优先级低于DataBinding的调度程序调用来推迟更改SelectedTabIndex。
this.Dispatcher.BeginInvoke(() => SelectedTabIndex = this.SearchTabs.IndexOf(addedTab), DispatcherPriority.Background);