基于标签的SelectedValue,而不是SelectedIndex的WPF MVVM烧码(WPF

2019-10-20 21:16发布

在WPF与MVVM很容易,当用户更改标签火一些代码。

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

然后在视图模型:

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

            if(value == 1)
            {
                //do something
            }
        }
    }
}

但我这个隐约感到不舒服。 如果其他开发商发生后沿,并在“1”的位置增加了一个选项卡。 如果这是关键应用的代码(这是),事情会打破壮观。

危险可以与单元测试被最小化,当然。 但它使我想知道:是这样看作是不好的做法? 而有没有这样做的一种方式,可以让你指的是标签一个字符串,而不是一个int? 我试图绑定到noodling SelectedValue属性,但似乎没有什么,当标签被改变的情况发生。

Answer 1:

你可以做的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作为命令参数的标签对象。



Answer 2:

如同所有的集控,保持所选项目的最好办法是使用SelectedItem属性。 如果数据绑定相关数据类型的的属性TabControl.SelectedItem属性 ,那么你仍然可以告诉选择哪个选项卡,然后从视图模型不同的一个。

用这种方法唯一的问题是,你还需要使用TabControl.ItemsSource属性来设置TabItem S:

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

如果您想尝试这一点,那么你应该知道,定义TabItem可以均为一点点混乱。 请参阅从回答一个TabControl如何绑定物品可观察集合在WPF? 对于与帮助的问题。



文章来源: WPF MVVM firing code based on Tab SelectedValue, rather than SelectedIndex
标签: c# wpf mvvm