2012-08-30 22 views
13

Sto tentando il mio primo progetto Windows Form, essendo stato interamente basato sul Web in precedenza e con alcuni problemi. Voglio associare un elenco di oggetti a un TabControl e fare in modo che crei le schede e quindi disporre di un valore di database accessibile dall'evento click di ogni scheda.Associazione dati a Windows Form TabControl

L'Oggetto Sono voler impegnare è

public class TreeNodeItem 
{ 
    private NTree<string> node; 

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

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

Il nodo NTree rappresenta un nodo in un oggetto che modelli di dati in una struttura ad albero. Voglio creare una scheda per ciascun oggetto nell'elenco con la proprietà Value associata alla proprietà Testo della scheda. Altri post menzionano il binding alla proprietà ItemsSource del controllo, ma Visual Studio non mi sta dando questa proprietà.

Qualsiasi aiuto sarà molto apprezzato.

Acclamazioni

Stewart

+2

Ogni volta che ho ho riscontrato una situazione del genere, avrei creato un controllo personalizzato (non ne ho visto uno pronto all'uso durante i miei 5 anni di sviluppo) o trovato un altro modo per rappresentare i dati. Ex. treeList control – Marty

+0

Questa è la cosa più facile da fare al mondo ... se si stesse usando 'WPF' invece di' winforms'. Se non sei investito in winform, ti suggerirei di utilizzare invece WPF. Ho spesso eseguito associazioni di dati a schede e contenuti di schede con i miei modelli di visualizzazione. Posso fornire un esempio se wpf è un'opzione. –

+0

@NathanA Lo so, vorrei usare WPF in quanto sarebbe stato così facile se fossi, comunque sono bloccato con WinForms – Rachel

risposta

2

Va bene, ero a conoscenza di che il vincolante era un must. Sebbene non abbia mai visto qualcosa di simile essere fatto in un'applicazione Windows Form, ho deciso di creare una classe che faccia questo per noi.

Utilizza lo ObservableCollection<T> per tenere traccia di se un oggetto/proprietà è stato modificato all'interno del suo elenco.

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 
      } 
     } 
    } 

Ora, dobbiamo creare una classe di supporto, che ci aiuta a tenere traccia:

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); 
        } 
       } 
      } 
     } 
    } 

Questo è un esempio su come usarlo:

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; 
    } 
+1

Questa domanda sta cercando un modo per * legare * la collezione TabPages ad una collezione di oggetti gerarchici e averli ottenere automaticamente generato e auto-aggiornato, invece di dover creare manualmente le pagine di tabulazione nel code-behind come questo. – Rachel

+0

Vedere di nuovo la mia risposta plea.se –

+0

Grazie per l'aggiornamento. Ho rimosso il mio downvote e testeremo per vedere se funziona o meno in seguito. Speravo che ci sarebbe stato un modo semplice per realizzare questo senza controlli personalizzati, tuttavia il suo aspetto non sarebbe il caso. Grazie :) – Rachel