WPF: TreeView в MVVM - PullRequest
       18

WPF: TreeView в MVVM

5 голосов
/ 22 июня 2011

У меня есть TreeView, который я (наконец) смог заполнить из базы данных, используя привязку данных.

В дереве есть 2 объекта:

  • FavoriteFolder - объект, который может иметь дочерние элементы: папки или отчеты.
  • FavoriteReport - объект, который не может иметь дочерних элементов: когда пользователь нажимает на этот элемент, он запускает отчет.

В настоящее время у меня есть настройка типа Model-View (я думаю), и я хотел бы изменить ее на MVVM, чтобы я мог делать вещи с TreeView -элементами, а не просто отображать их.

Я посмотрел много примеров, но я все еще новичок в MVVM и WPF в целом, поэтому любые рекомендации для моего конкретного примера будут высоко оценены

Мои два класса, которые существуют в TreeView:

Папка:

public class FavoriteFolder
{
    private string _connectionString = new ServerInfo().ConnectionString;
    private string _folderID;
    private string _parentID;
    private string _folderTitle;

    private ObservableCollection<FavoriteFolder> _folders;
    private ObservableCollection<FavoriteReport> _reports;
    private ObservableCollection<object> _children;

    public FavoriteFolder()
    {

    }

    public ObservableCollection<object> Children
    {
        get 
        {
            _getChildren();
            return _children; 
        }
    }

    public string FolderID
    {
        get { return _folderID; }
        set { _folderID = value; }
    }

    public string ParentID
    {
        get { return _parentID; }
        set { _parentID = value; }
    }

    public string FolderTitle
    {
        get { return _folderTitle; }
        set { _folderTitle = value; }
    }

    private void _getChildren()
    {
        _folders = new ObservableCollection<FavoriteFolder>();
        _reports = new ObservableCollection<FavoriteReport>();

        using (SqlConnection cnn = new SqlConnection(_connectionString))
        {
            cnn.Open();
            string sql = "SELECT * FROM tbl_report_folders where fdr_parent_id =" + _folderID;
            SqlCommand cmd = new SqlCommand(sql, cnn);

            SqlDataReader reader = cmd.ExecuteReader();

            while (reader.Read())
            {
                FavoriteFolder folder = new FavoriteFolder();

                folder.FolderID = reader["fdr_folder_id"].ToString();
                folder.FolderTitle = reader["fdr_folder_name"].ToString();
                folder.ParentID = reader["fdr_parent_id"].ToString();

                _folders.Add(folder);
            }

            reader.Close();

            sql = "SELECT * FROM tbl_reports where rpt_folder_id =" + _folderID;
            cmd = new SqlCommand(sql, cnn);

            reader = cmd.ExecuteReader();

            while (reader.Read())
            {
                FavoriteReport report = new FavoriteReport();

                report.ReportID = reader["rpt_report_id"].ToString();
                report.ReportTitle = reader["rpt_report_name"].ToString();
                report.ParentID = reader["rpt_folder_id"].ToString();

                _reports.Add(report);
            }
        }

        //add the children to the collection
        foreach (var folder in this._folders)
            _children.Add(folder);

        foreach (var report in this._reports)
            _children.Add(report);
    }
}

Элементы отчета:

public class FavoriteReport
{
    private string _reportID;
    private string _parentID;
    private string _reportTitle;

    public FavoriteReport()
    {

    }

    public string ReportID
    {
        get { return _reportID; }
        set { _reportID = value; }
    }

    public string ParentID
    {
        get { return _parentID; }
        set { _parentID = value; }
    }

    public string ReportTitle
    {
        get { return _reportTitle; }
        set { _reportTitle = value; }
    }
}

И MainWindow.xaml.cs -

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        ObservableCollection<object> items = new ObservableCollection<object>();

        FavoriteFolder fdr = new FavoriteFolder();

        fdr.FolderID = "0";

        items = fdr.Children;

        this.DataContext = items;
    }
}

Ответы [ 2 ]

4 голосов
/ 23 июня 2011

Моя первая рекомендация - добавить инструментарий MVVM, так как это проще, чем делать все самостоятельно (например, реализовать интерфейс INotifyPropertyChanged).Я использую MVVM Light от Laurent Bungion .

Предполагая, что вы используете MVVM Light (вы можете экстраполировать его, если используете другой инструментарий) ...

Итак, чтобы преобразовать это в MVVM, вам нужно сделать несколько вещей.

  1. Создать определенный Models.Я обычно использую POCO, просто определяя свойства модели.Это означает абстрагирование вашего уровня доступа к данным (подробнее ниже).

  2. Создайте свой ViewModel.Это то место, где у вас есть свои свойства, которые вы обязываете в своем обзоре.Ваш ObservableCollections будет сидеть здесь.Инициализация экземпляра созданных вами классов будет здесь.Звонки на ваш уровень DAL будут идти сюда.(например, вместо конструктора вашего представления).

    Добавьте этот ViewModel к вашему ViewModelLocator (я использую фрагмент кода mvvmlocatorproperty, предоставленный в MVVM Light).

    Свяжите свой View с ViewModel, используя Locator.В вашем UserControl вы бы добавили что-то подобное в декларацию:

    DataContext="{Binding YourViewModel, Source={StaticResource Locator}}"
    
  3. Я бы последовал совету Бреннана Винсента.Обычно я создаю интерфейс службы (примечание: не класс, а интерфейс), который определяет методы, которые будут иметь мой DAL (уровень доступа к данным).Я делаю это, чтобы учесть Blendability, то есть данные времени проектирования.Если вы не знакомы с интерфейсами, возможно, просто начать класс DAL.Затем я использую внедрение зависимостей (DI), чтобы внедрить экземпляр моей службы DAL.DI довольно прост - в ViewModelLocator вам нужно обновить (создать экземпляр) свой класс обслуживания DAL и передать его через ваш vm = New ViewModel(MyDALService dalService) вызов.Тогда вам, очевидно, необходимо принять ссылку MyDALService в конструкторе ViewModel.Вот пример моего EquipmentViewModel конструктора для проекта, над которым я работал:

    public EquipmentViewModel(Services.IEquipmentService equipmentService)
    {
        EquipmentService = equipmentService;
        LoadData();
    }
    

Этот ViewModel принимает параметр типа IEquipmentService (который является моиминтерфейс).В методе LoadData я вызываю метод EquipmentService.GetEquipment() моего DAL, который попадает на уровень моей базы данных.

Любые вопросы сообщают мне.MVVM может быть болью, но я очень рад, что застрял с этим.Удачи.:)

2 голосов
/ 23 июня 2011

Джош Смит дал исчерпывающее описание того, как использовать MVVM для упрощения TreeView Не так много я могу добавить к нему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...