wpf 绑定到 TabControl SelectedIndex
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12162577/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Binding to TabControl SelectedIndex
提问by Adrian Hand
I have a tab control on a page; its items are bound back to my ViewModel, which also exposes an ActiveTabItemIndex which is bound (two way) to the SelectedIndex property in my xaml, and which implements INotifyPropertyChanged so that my TabControl knows when to update.
我在页面上有一个选项卡控件;它的项目绑定回我的 ViewModel,它也公开一个 ActiveTabItemIndex,它绑定(两种方式)到我的 xaml 中的 SelectedIndex 属性,并实现 INotifyPropertyChanged,以便我的 TabControl 知道何时更新。
This is (I understand) the MVVM-correct way to do things, and works 99% properly.
这是(我理解)MVVM 正确的做事方式,并且可以正常工作 99%。
class MainWindowViewModel : BaseViewModel, INotifyPropertyChanged
{
ObservableCollection<TabItemViewModel> _TabItems;
int _ActiveTabItemIndex;
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(name));
}
void _TabItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
_ActiveTabItemIndex = _TabItems.IndexOf((TabItemViewModel)e.NewItems[0]);
RaisePropertyChanged("ActiveTabItemIndex");
}
public ObservableCollection<TabItemViewModel> TabItems
{
get
{
if (_TabItems == null)
{
_TabItems = new ObservableCollection<TabItemViewModel>();
_TabItems.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_TabItems_CollectionChanged);
}
return _TabItems;
}
}
public int ActiveTabItemIndex
{
get
{
return _ActiveTabItemIndex;
}
set
{
_ActiveTabItemIndex = value;
}
}
}
This way any manipulations I make to my TabItems collection are reflected on the TabControl, and when I add a new item, it is automatically selected. This works a treat; however, when adding the very first item to an empty tab control, it looks like this:
这样,我对 TabItems 集合所做的任何操作都会反映在 TabControl 上,并且当我添加新项目时,它会被自动选中。这是一种享受;但是,将第一个项目添加到空选项卡控件时,它看起来像这样:


The tab contents are displayed, but the tab is not selected. I need to manually click the tab to get it to look right:
显示选项卡内容,但未选择选项卡。我需要手动单击选项卡以使其看起来正确:


It is as though there is some kind of disconnect between the drawing of the tabs and the drawing of their contents. I know the binding is working because subsequent tabs are handled correctly and if I remove the binding altogether then the first page does not show its contents until the tab is manually selected. If anyone has seen this or can shed some light it would be very much appreciated! Thank you all :)
就好像选项卡的绘制与其内容的绘制之间存在某种脱节。我知道绑定正在工作,因为后续选项卡被正确处理,如果我完全删除绑定,那么在手动选择选项卡之前,第一页不会显示其内容。如果有人看过这个或可以解释一下,将不胜感激!谢谢你们 :)
采纳答案by humanitas
Only raise your property change events in the setter; you can think of it as allowing the property itself to dictate what "changed" means, and by extension, giving it control over when the event is fired (and makes it do what you expect):
仅在 setter 中引发您的属性更改事件;您可以将其视为允许属性本身决定“更改”的含义,并且通过扩展,让它控制事件何时被触发(并使其按照您的期望执行):
public int ActiveTabItemIndex
{
get{ return _ActiveTabItemIndex; }
set
{
if(_ActiveTabItemIndex != value)
{
_ActiveTabItemIndex = value;
RaisePropertyChanged("ActiveTabItemIndex");
}
}
}
Just change
只是改变
_ActiveTabItemIndex = _TabItems.IndexOf(...);
to
到
ActiveTabItemIndex = _TabItems.IndexOf(...);
and remove the RaisePropertyChanged call from _TabItems_CollectionChanged
并从 _TabItems_CollectionChanged 中删除 RaisePropertyChanged 调用
There will be times when you'll need raise property changed notifications outside a property's setter but that is for a far more complicated day :)
有时您需要在属性的 setter 之外引发属性更改通知,但那是要复杂得多的一天:)
As an aside, INotifyPropertyChanged should be implemented on your BaseViewModel. Check out the absolutely fantastic MVVM Light Toolkit- it has all the code you'd otherwise have to duplicate in every project that you use MVVM in.
顺便说一句,INotifyPropertyChanged 应该在您的 BaseViewModel 上实现。查看绝对出色的MVVM Light Toolkit- 它包含您在使用 MVVM 的每个项目中必须复制的所有代码。

