【问题标题】:How to save the tab order of tabcontrol items which are bound to an ObservableCollection in wpf?如何保存绑定到 wpf 中 ObservableCollection 的选项卡控件项的选项卡顺序?
【发布时间】:2026-02-12 07:55:01
【问题描述】:

我有一个绑定到 tabcontrol 的 ObservableCollection。

<TabControl
    ItemsSource="{Binding Steps}"
    SelectedItem="{Binding SelectedStep}"
    CanUserReorder="{Binding EditMode}"
</TabControl>

如果他处于编辑模式,用户可以重新排序选项卡项目。 当我使用 tabcontrol 离开视图时,我丢失了用户修改的 tab 顺序。 我怎样才能防止这种情况发生?

感谢您的帮助!

【问题讨论】:

  • CanUserReorder 属性从何而来?
  • 另外,可能重复*.com/questions/9877125/…
  • 来自附加到该视图的视图模型。这是一个布尔属性。
  • 抱歉,您的评论有误。我正在使用“组件一”中的选项卡控件,它提供 CanUserReorder 属性
  • 好的,谢谢。熟悉该控件的其他人可能会更好地回答。祝你好运!

标签: c# wpf mvvm tabcontrol


【解决方案1】:

我明白了! 这个解决方案是在 mvvm-pattern 中实现的。

每次集合步骤发生变化时,添加或删除项目,然后重新排列它们的位置。 View 中 TabControl 的 TabItems 可以由用户通过使用 ComponentOne 的 TabControl 或使用 Bea Stollnitz 的拖放功能重新排序。

视图模型:

public class MyViewModel
{
    public MyModel Model {/*get... set*/}
    public ObservableCollection<StepViewModel> Steps {/*get... set...*/}
    public StepViewModel SelectedStep {/*get... set...*/}

    public MyViewModel()
    {
        Model = new MyModel();
        Steps = new ObservableCollection<StepViewModel>();
        Model.Steps = new ObservableCollection<StepModel>();
        // Load the saved Model with the steps and their positions
        Model.Steps = LoadFromXml();

        Steps.CollectionChanged += Steps_OnCollectionChanged;
        // Add the Steps in the right order
        for (int i = 0; i < Steps.Count; i++)
        {
             var item = Steps.First(x => x.Position == i);
             var vm = new StepViewModel();
             Steps.Add(vm);
        }
    }

    private void Steps_OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == NotifyCollectionChangedAction.Add)
        {
            foreach (StepViewModel vm in e.NewItems)
            {
                if (!Model.Steps.Contains(vm.Model))
                    Model.Steps.Add(vm.Model);
            }
        }
        else if (e.Action == NotifyCollectionChangedAction.Remove)
        {
            foreach (StepViewModel vm in e.OldItems)
            {
                if (Model.Steps.Contains(vm.Model))
                    Model.Steps.Remove(vm.Model);
            }
        }
        // Match the temporary collectionindex to a position-property
        foreach (StepViewModel item in Steps)
        {
            item.Position = Steps.IndexOf(item);
        }
    }

}

【讨论】: