Silverlight Toolkit Bug (发生在 TabControl 里的 TreeView 身上)

Silverlight

描述:

将Microsoft.Windows.Controls.TreeView置入System.Windows.Controls.TabControl中, 并且选中TreeViewItem时, 如果切换TabItem, 你会发现树节点的焦点从选中那一项开始依次向下切换, 直到最末一项, 其中包括已展开的所有条目.

重现:

前端模板:

#!xml
<usercontrol x:class="TreeViewFocus.Page"
                    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:microsoft_windows_controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls"
                    xmlns:system_windows_controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls">
	<stackpanel x:name="LayoutRoot" background="White" orientation="Horizontal" margin="16">
	  <system_windows_controls:tabcontrol x:name="tabcontrol" width="150">
	  	<system_windows_controls:tabitem header="一">
				<microsoft_windows_controls:treeview x:name="treeview">
					<microsoft_windows_controls:treeview.itemtemplate>
						<microsoft_windows_controls:hierarchicaldatatemplate itemssource="{Binding Path=Child}">
							<contentcontrol content="{Binding Path=Name}" />
						</microsoft_windows_controls:hierarchicaldatatemplate>
					</microsoft_windows_controls:treeview.itemtemplate>
				</microsoft_windows_controls:treeview>
			</system_windows_controls:tabitem>
			<system_windows_controls:tabitem header="二">
				<textblock text="Look Right :(" fontsize="16" foreground="Red"/>
			</system_windows_controls:tabitem>
		</system_windows_controls:tabcontrol>
		<textbox x:name="textbox"/>
	</stackpanel>
</usercontrol>

后端代码:

#!csharp
// 随便定义一个类用于数据源
public class Person
{
    public string Name { get; set; }
    public ObservableCollection<Person> Child { get; set; }
    public override string ToString() { return Name; }
}

public Page()
{
    InitializeComponent();
    // 随便填充点数据
    var source = new ObservableCollection<Person> {
        new Person{Name="蓝皮鼠"},
        new Person{Name="大脸猫"},
        new Person{Name="小头爸爸", Child = new ObservableCollection<Person>{new Person{Name="大头儿子"}}}
    };
    // 绑定到 TreeView (模板已经设置好了)
    treeview.ItemsSource = source;
    // 当 TreeView 的选中项发生变化时, 输出到右侧的文本框中.
    treeview.SelectedItemChanged += (s, e) =>
    {
        textbox.Text += e.NewValue == null ? "" : e.NewValue.ToString() + "\n";
    };
}

OK, 让我们看看发生了什么(图有些难看…):

标签切换的瞬间, 树像是被一阵风吹过, 焦点从不至下依次选中过, 顺序与按键盘上的TAB键时的情形相似.

我还曾经试过ListBox, 并没有发现这一问题, 可以肯定的说这是个BUG了.

怎么解决呢? 办法有点以暴治暴的感觉, 失去焦点的标签, 如果有内容, 暂时将内容禁用, 当标签获得焦点时再次启用:

#!csharp
tabcontrol.SelectionChanged += (s, e) =>
{
    if (e.RemovedItems != null && e.RemovedItems.Count > 0)
    {
        var tab = e.RemovedItems.Cast<TabItem>().First();
        if (tab.Content != null) (tab.Content as Control).IsEnabled = false;
    }
    if (e.AddedItems != null && e.AddedItems.Count > 0)
    {
        var tab = e.AddedItems.Cast<TabItem>().First();
        if (tab.Content != null) (tab.Content as Control).IsEnabled = true;
    }
};

打完收工~~~