【问题标题】:Bind Data to Windows Form TabControl将数据绑定到 Windows 窗体 TabControl
【发布时间】:2014-05-30 09:29:27
【问题描述】:

我正在尝试我的第一个 Windows 窗体项目,之前完全基于 Web 并遇到了一些问题。我想将对象列表绑定到 TabControl 并让它创建选项卡,然后从每个选项卡的单击事件中访问数据绑定值。

我要绑定的对象是

public class TreeNodeItem
{
    private NTree<string> node;

    public TreeNodeItem(NTree<string> node)
    {
        this.node = node;
    }

    public string Value
    {
        get { return this.node.data; }
    }
}

NTree 节点表示对象中的一个节点,该对象对树结构中的数据进行建模。我想为列表中的每个对象创建一个选项卡,并将 Value 属性绑定到 Tab Text 属性。其他帖子提到绑定到控件的 ItemsSource 属性,但 Visual Studio 没有给我这个属性。

任何帮助将不胜感激。

干杯

斯图尔特

【问题讨论】:

  • 每次遇到这种情况,我要么构建一个自定义控件(在我 5 年的开发工作中还没有见过一个开箱即用的控件),要么找到另一种方式来表示数据。前任。树列表控件
  • 这是世界上最简单的事情...如果您使用WPF 而不是winforms。如果您没有使用winforms,我建议您改用WPF。我经常使用我的视图模型对选项卡和选项卡页面内容进行数据绑定。如果 wpf 是一个选项,我可以提供一个示例。
  • @NathanA 我知道,我希望我使用 WPF,因为如果我这样做会很容易,但是我坚持使用 WinForms
  • @Rachel 我想这一切都归结为“winforms 心态”(与我们一直在谈论的“WPF 心态”形成对比)。 winforms 并不真正支持数据绑定,它的设计初衷并非如此,因此您需要手动完成所有这些工作:S

标签: c# winforms tabcontrol


【解决方案1】:

好的,我不知道 绑定 是必须的。虽然我从未见过在 Windows 窗体应用程序中执行过类似的操作,但我决定创建一个类来为我们执行此操作。

它使用ObservableCollection&lt;T&gt; 来跟踪其列表中的对象/属性是否已更改。

    public class ObservableList<T> : ObservableCollection<T>
    {
        public ObservableList() : base()
        {
            CollectionChanged += new NotifyCollectionChangedEventHandler(nObservableCollection_CollectionChanged);
        }

        public event PropertyChangedEventHandler OnPropertyChanged;

        void nObservableCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (OnPropertyChanged != null)
            {
                OnPropertyChanged(new object[] { e.OldItems, e.NewItems }, null); // Call method to let it change the tabpages
            }
        }
    }

现在,我们必须创建一个帮助类来帮助我们跟踪:

    public class TabControlBind
    {
        public TabControlBind(TabControl tabControl)
        {
            // Create a new TabPageCollection and bind it to our tabcontrol
            this._tabPages = new TabControl.TabPageCollection(tabControl);
        }

        // Fields
        private ObservableList<TreeNodeItem> _treeNodeItems;
        private TabControl.TabPageCollection _tabPages;

        // Properties
        public ObservableList<TreeNodeItem> TreeNodeItems
        {
            get { return _treeNodeItems; }
            set
            {
                if (_treeNodeItems != value)
                {
                    _treeNodeItems = value;
                    _treeNodeItems.OnPropertyChanged += OnPropretyChanged;
                    OnPropretyChanged(null, null);
                }
            }
        }

        public TabControl.TabPageCollection TabPages
        {
            get
            {
                return this._tabPages;
            }
        }

        // Events
        private void OnPropretyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (sender == null) // If list got set
            {
                // Remove existing tabpages
                this._tabPages.Clear();

                // Loop through all items inside the ObservableList object and add them to the Tabpage
                foreach (TreeNodeItem _treeNodeItem in this._treeNodeItems)
                {
                    TabPage tabPage = new TabPage() { Text = _treeNodeItem.Value, Tag = _treeNodeItems };
                    this._tabPages.Add(tabPage);
                }
            }
            else if (sender is object[]) // If only one (or multiple) objects have been changed
            {
                // Get OldItems and NewItems
                object[] changedItems = (object[])sender;
                // Remove OldItems
                if (changedItems[0] != null)
                {
                    foreach (dynamic oldItems in (IList)changedItems[0])
                    {
                        foreach (TabPage tab in this._tabPages)
                        {
                            if (tab.Text == oldItems.Value)
                            {
                                this._tabPages.Remove(tab);
                                break;
                            }
                        }

                    }
                }
                // Add OldItems
                if (changedItems[1] != null)
                {
                    foreach (dynamic newItems in (IList)changedItems[1])
                    {
                        TabPage tabPage = new TabPage() { Text = newItems.Value, Tag = newItems };
                        this._tabPages.Add(tabPage);
                    }
                }
            }
        }
    }

这是一个如何使用它的示例:

    TabControlBind tabControlBinder;
    ObservableList<TreeNodeItem> treeNodeItems;

    private void btnAdd_Click(object sender, EventArgs e)
    {
        // This will automatically update the TabControl
        treeNodeItems.Add(new TreeNodeItem(new NTree<string>() { data = "Test3" }));
    }

    private void frmMain_Load(object sender, EventArgs e)
    {
        // Create a new list object an add items to it
        treeNodeItems = new ObservableList<TreeNodeItem>();
        treeNodeItems.Add(new TreeNodeItem(new NTree<string>() { data = "Test" }));
        treeNodeItems.Add(new TreeNodeItem(new NTree<string>() { data = "Test2" }));

        // Create a new instance of the TabControlBind class, set it to our TabControl
        tabControlBinder = new TabControlBind(tabControl);
        tabControlBinder.TreeNodeItems = treeNodeItems;
    }

【讨论】:

  • 这个问题正在寻找一种将 TabPages 集合绑定到分层对象集合并让它们自动生成和自动更新的方法,而不必创建像这样在代码隐藏中手动设置标签页。
  • 请再次查看我的答案。se
  • 感谢您的更新。我已经删除了我的反对票,并将在以后测试它是否有效。我曾希望有一种简单的方法可以在没有自定义控件的情况下完成此操作,但看起来情况并非如此。谢谢:)
  • 我也尝试过寻找一种更简单的方法,但似乎没有。我很想听听您的意见,这是否(对您)有效!
  • 它确实有点工作.... 项目确实会被添加和删除,但是绑定设置的方式意味着每次添加或删除项目时都会重新创建 TabPages,这并不理想.此外,选项卡标题之类的内容无法正确响应更改通知。我怀疑我需要编写一个自定义控件来执行此操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-07
  • 1970-01-01
  • 2013-04-11
  • 2017-02-27
相关资源
最近更新 更多