94 messaggi dal 09 novembre 2005
Ciao a tutti,
mi chiedevo se esiste un pattern (accreditato) per poter popolare una treeview rispettando MVVM.
Mi spiego meglio:
Partendo da un db dove ho una tabella Partent-Child che mi definisce in sostanza la struttura della treeview.
Mi creo un model speculare, una collection .......... non so definirla e poi configurare il tutto per poter "bindare" una treeview.
Però vorrei anche poter "filtrare" la TreeView specificando un nodo, quindi l'effetto dovrebbe essere che specificato un nodo (magari da un altro controllo) nella treeview mi appare il nodo con tutto il suo ramo?
Quello che so ad oggi (molto poco me tapino) è che creo il modello Parent-Child ereditando INotifyPropertyChanged, poi una classe dove eredito una ObservableCollection<"Partent-Child">, ma qui mi fermo.

Una volta risolto questo c'é il problema della possibilità di filtrare, quindi immagino debba usare una CollectionView???

C'é qualche pattern?

Grazie a tutti.

Dario
Ciao,
il problema del TreeView e della sorgente che ha bisogno, è che la struttura è multi livello e la sincronizzazione della view non avviene.
In pratica un TreeView ha una lista e ogni TreeViewItem ha una sua sottolista.
In questi dunque abbandono l'uso di ICollectionView e i suoi eventi e espongo una proprietà "SelectedItem" nel mio ViewModel, messa in binding sulla proprietà SelectedItem del TreeView. All'interno della proprietà poi posso decidere di caricare la collezione figlia, filtrare e posso mettere in binding SelectedItem con un'altra lista e così via

Ciao

Il mio blog
Homepage
94 messaggi dal 09 novembre 2005
Ho letto attentamente la tua risposta e adesso sono in confusione. Ho ancora difficoltà ad approcciarmi con il Binding della TreeView.

Questo è il mio Model Location
 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.ComponentModel; 
using System.Collections.ObjectModel; 
using System.Windows.Markup; 
 
namespace WpfTreeViewMVVM 
{ 
 
    public class Location : INotifyPropertyChanged 
    { 
        public event PropertyChangedEventHandler PropertyChanged; 
 
        private Int32 _ID; 
        private string _Name; 
        private Int32 _ParentID; 
        private ObservableCollection<Location> _Children; 
 
        public Int32 ID 
        { 
            get { return _ID; } 
            set 
            { 
                _ID = value; 
                this.OnPropertyChanged("ID"); 
            } 
        } 
 
        public string Name 
        { 
            get { return _Name; } 
            set 
            { 
                _Name = value; 
                this.OnPropertyChanged("Name"); 
            } 
        } 
 
        public Int32 ParentID 
        { 
            get { return _ParentID; } 
            set 
            { 
                _ParentID = value; 
                this.OnPropertyChanged("ParentID"); 
            } 
        } 
 
        public ObservableCollection<Location> Children 
        { 
            get { return _Children; } 
            set { _Children = value; } 
        } 
 
        #region Internals 
        protected void OnPropertyChanged(string propertyName) 
        { 
            if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
        } 
        #endregion 
    } 
} 


La classe provider che mi fornisce un ObservableCollection<Location>

 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Collections.ObjectModel; 
using WpfTreeViewMVVM.Properties; 
 
namespace WpfTreeViewMVVM 
{ 
    public static class DataGenerator 
    { 
        public static ObservableCollection<Location> Locations() 
        { 
            ObservableCollection<Location> _locations = new ObservableCollection<Location>(); 
 
            using (Model1Container _dc = new Model1Container()) 
            { 
                var _root = from rec in _dc.Names 
                            where rec.ParentID == null 
                            select rec; 
                if (_root.Count() > 0) 
                { 
                    foreach (Names _n in _root) 
                    { 
                        Location _new = new Location(); 
                        _new.ID = _n.ID; 
                        _new.Name = _n.Name; 
                        _new.Children = GetChildren(_new); 
 
                        _locations.Add(_new); 
                    } 
 
                } 
 
            } 
 
            return _locations; 
        } 
 
        public static ObservableCollection<Location> GetChildren(Location par_LocationParent) 
        { 
            ObservableCollection<Location> _locationResult = new ObservableCollection<Location>(); 
 
            using (Model1Container _dc = new Model1Container()) 
            { 
                var _children = from rec in _dc.Names 
                                where rec.ParentID == par_LocationParent.ID 
                                select rec; 
                if (_children.Count() > 0) 
                { 
                    foreach (Names _n in _children) 
                    { 
                        Location _new = new Location(); 
                        _new.ID = _n.ID; 
                        _new.Name = _n.Name; 
                        _new.Children = GetChildren(_new); 
 
                        _locationResult.Add(_new); 
                    } 
                } 
            } 
 
            return _locationResult; 
        } 
    } 
 
} 


Questo è il ViewModel
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.ComponentModel; 
using System.Windows.Input; 
using System.Collections.ObjectModel; 
 
namespace WpfTreeViewMVVM 
{ 
    public class MainViewModel : INotifyPropertyChanged 
    { 
        private ObservableCollection<Location> _Locations; 
 
        public MainViewModel() 
        { 
            // Set Sample Tree Data 
            Locations = DataGenerator.Locations(); 
        } 
 
        public ObservableCollection<Location> Locations 
        { 
            get { return _Locations; } 
            private set 
            { 
                if (_Locations == value) 
                { 
                    return; 
                } 
                _Locations = value; 
                this.NotifyPropertyChanged("Locations"); 
            } 
        } 
 
        #region INotifyPropertyChanged 
        public event PropertyChangedEventHandler PropertyChanged; 
        private void NotifyPropertyChanged(String info) 
        { 
            if (PropertyChanged != null) 
            { 
                PropertyChanged(this, new PropertyChangedEventArgs(info)); 
            } 
        } 
        #endregion 
 
    } 
} 


Infine lo XAML
<Window x:Class="WpfTreeViewMVVM.MainWindow" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        Title="MainWindow" Height="350" Width="525"> 
  <StackPanel> 
        <TreeView ItemsSource="{Binding Locations}" Width="300" Height="300"> 
            <HierarchicalDataTemplate ItemsSource="{Binding Children}"> 
                <TextBlock Text="{Binding Name}"/> 
            </HierarchicalDataTemplate> 
        </TreeView> 
    </StackPanel> 
</Window>


L'effetto è che appare la treeview vuota con una riga
con scritto System.Windows.HierarchicalDataTemplate ho l'impressione (oltre a sentirmi idiota) di omettere qualcosa di basilare.

Che dici?

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.