WPF MVVM激发基于选项卡SelectedValue而非SelectedIndex的代码



在带有MVVM的WPF中,当用户更改选项卡时,很容易激发一些代码。

<TabControl Margin="0 5 5 5" Background="#66F9F9F9" SelectedIndex="{Binding TabIndex}">

然后在ViewModel中:

private int _tabIndex;
public int TabIndex
{
    get { return _tabIndex; }
    set
    {
        if(_tabIndex != value)
        {
            _tabIndex = value;
            OnPropertyChanged("TabIndex");
            if(value == 1)
            {
                //do something
            }
        }
    }
}

但我对此有点不舒服。如果另一个开发人员稍后出现,并在"1"位置添加另一个选项卡,该怎么办。如果这是应用程序关键型代码(事实就是这样),那么事情就会大不相同。

当然,通过单元测试可以将危险降至最低。但这让我想知道:这被视为不好的做法吗?有没有一种方法可以让你用字符串而不是int引用Tab?我尝试了绑定到SelectedValue属性,但在更改选项卡时似乎什么也没发生。

您可以为TabItem创建一个行为,监听对IsSelected依赖属性的更改,并在选择选项卡时引发一个命令。这可以扩展到任意数量的选项卡,每个选项卡调用视图模型中的不同命令。您还可以为任何可选上下文提供命令参数:

class TabSelectedBehavior : Behavior<TabItem>
{
    public static readonly DependencyProperty SelectedCommandProperty = DependencyProperty.Register("SelectedCommand", typeof(ICommand), typeof(TabSelectedBehavior));
    public ICommand SelectedCommand
    {
        get { return (ICommand)GetValue(SelectedCommandProperty); }
        set { SetValue(SelectedCommandProperty, value); }
    }
    private EventHandler _selectedHandler;
    protected override void OnAttached()
    {
        DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(TabItem.IsSelectedProperty, typeof(TabItem));
        if (dpd != null)
        {
            _selectedHandler = new EventHandler(AssociatedObject_SelectedChanged);
            dpd.AddValueChanged(AssociatedObject, _selectedHandler);
        }
        base.OnAttached();
    }
    protected override void OnDetaching()
    {
        DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(TabItem.IsSelectedProperty, typeof(TabItem));
        if (dpd != null && _selectedHandler != null)
        {
            dpd.RemoveValueChanged(AssociatedObject, _selectedHandler);
        }
        base.OnDetaching();
    }
    void AssociatedObject_SelectedChanged(object sender, EventArgs e)
    {
        if (AssociatedObject.IsSelected)
        {
            if (SelectedCommand != null)
            {
                SelectedCommand.Execute(null);
            }
        }
    }
}

XAML

<TabControl>
    <TabItem Header="TabItem1">
            <i:Interaction.Behaviors>
                <local:TabSelectedBehavior SelectedCommand="{Binding TabSelectedCommand}"/>
            </i:Interaction.Behaviors>
        </TabItem>
        <TabItem Header="TabItem2">
    </TabItem>
</TabControl>

以类似的方式,您也可以为TabControl创建行为,将SelectionChanged事件转换为命令,并将所选TabItem的Tag对象作为命令参数传递。

与所有集合控件一样,维护所选项的最佳方法是使用SelectedItem属性。如果将相关数据类型的属性数据绑定到TabControl.SelectedItem属性,则仍然可以判断选择了哪个选项卡,并从视图模型中选择不同的选项卡。

此方法的唯一问题是,您还需要使用TabControl.ItemsSource属性来设置TabItem s:

<TabControl ItemsSource="{Binding YourDataItems}" SelectedItem="{Binding YourItem}" />

如果您想尝试这样做,那么您应该知道定义TabItem可能有点令人困惑。请参阅如何将TabControl的项绑定到wpf中的可观察集合?寻求帮助。

最新更新