使用 MVVM 将新项目添加到 TabControl ItemSsource 时选择最后一个 TabItem
Posted
技术标签:
【中文标题】使用 MVVM 将新项目添加到 TabControl ItemSsource 时选择最后一个 TabItem【英文标题】:Selecting the last TabItem when new items are added to a TabControl's ItemSource using MVVM 【发布时间】:2021-10-11 10:46:37 【问题描述】:我通过将ItemsSource
绑定到MyUnicornsViewModel
创建了一个动态生成的TabControl
。
随着新项目被添加到MyUnicornsViewModel
... 新标签项目被创建。但是,TabControl
中不会自动选择新添加的选项卡。
如何在添加新标签时选择它们?
<TabControl ItemsSource="Binding MyUnicornsViewModel" SelectedItem="Binding SelectedItem">
<TabControl.ItemTemplate>
<!-- header template -->
<DataTemplate>
<TextBlock Text="Binding Name" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<!-- body template-->
<DataTemplate>
<TextBlock Text="Binding Content" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
起初,我希望TabControl
中有“ItemsChanged”或“ItemAdded”事件,这样我可以在添加新项目时在代码隐藏中设置 SelectedIndex。
我尝试的另一件事是将TabControl.SelectedItem
绑定到MyUnicornsViewModel
中的SelectedItem
属性。可悲的是,这也不起作用。
MyUnicornsViewModel:
public class MyUnicornsViewModel : ObservableCollection<UnicornViewModel>
...
private void AddNewUnicorn()
var awesomeUnicorn = new UnicornViewModel();
Add(awesomeUnicorn);
SelectedItem = awesomeUnicorn; //I expected my TabControl to have 'awesomeUnicorn' selected.
public UnicornViewModel SelectedItem get; set;
【问题讨论】:
【参考方案1】:这里有几个问题:
-
从
ObservableCollection
派生“视图模型”非常奇怪。视图模型应该包含一个可观察的集合。
视图模型需要实现INotifyPropertyChanged
接口;从提供的代码中不清楚UnicornViewModel
是否实现了这个接口,但是MyUnicornsViewModel
绝对没有。
以下是一些建议:
-
实现
INotifyPropertyChanged
接口的视图模型基类将真正帮助您完成大部分工作。您可以使用 INotifyPropertyChanged documentation 编写自己的代码,或者寻找适合您项目的 MVVM 框架(例如 Prism、MVVM Light、ReactiveUI)。其中每一个都将提供一个用于视图模型的基类 - BindableBase
、ViewModelBase
、ReactiveObject
,分别用于上述每个框架。
MyUnicornsViewModel
应该有:
一个ObservableCollection
,用于收集独角兽;这将绑定到您的TabControl
上的ItemsSource
属性。
SelectedItem
属性在设置时必须触发 PropertyChanged
事件。
这是一个使用 Prism 的快速示例:
public sealed class UnicornViewModel : BindableBase
public UnicornViewModel(string name, string content)
Name = name;
Content = content;
// these properties don't change and therefore don't need to raise property changed
public string Name get;
public string Content get;
public sealed class UnicornsViewModel : BindableBase
private UnicornViewModel _selectedUnicorn;
public UnicornsViewModel()
AddUnicornCommand = new DelegateCommand(AddUnicorn);
ClearUnicornsCommand = new DelegateCommand(ClearUnicorns, () => HasUnicorns).ObservesProperty(() => HasUnicorns);
public ObservableCollection<UnicornViewModel> Unicorns get; = new ObservableCollection<UnicornViewModel>();
public UnicornViewModel SelectedUnicorn
get => _selectedUnicorn;
set => SetProperty(ref _selectedUnicorn, value, () => RaisePropertyChanged(nameof(HasUnicorns)));
public DelegateCommand AddUnicornCommand get;
public DelegateCommand ClearUnicornsCommand get;
private bool HasUnicorns => Unicorns.Any(); // helper property for the clear command's can execute
private void AddUnicorn()
Unicorns.Add(new UnicornViewModel($"Unicorn Unicorns.Count + 1", Guid.NewGuid().ToString()));
SelectedUnicorn = Unicorns.Last();
private void ClearUnicorns()
SelectedUnicorn = null;
Unicorns.Clear();
【讨论】:
以上是关于使用 MVVM 将新项目添加到 TabControl ItemSsource 时选择最后一个 TabItem的主要内容,如果未能解决你的问题,请参考以下文章
Xamarin.Forms 条目 - 自定义行为和 MVVM