WPF:MVVM中的TreeView

Cha*_*ams 5 c# wpf treeview xaml mvvm

我有一个TreeView(最终)可以使用数据绑定从数据库中填充数据的功能。

树中有2个对象:

  • FavoriteFolder-可以有子级的对象:文件夹或报表。
  • FavoriteReport —一个不能有任何子级的对象:当用户单击此项目时,它将运行报告。

目前,我有一个Model-View类型设置(我认为),我想将其更改为MVVM,这样我就可以使用TreeView-items进行操作,而不是简单地显示它们。

我看了很多示例,但是总体上我还是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);
    }
}
Run Code Online (Sandbox Code Playgroud)

报告项目:

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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

还有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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Sco*_*lvi 4

我的第一个建议是使用 MVVM 工具包,因为它比必须自己做所有事情(例如实现接口INotifyPropertyChanged)更容易。我使用Laurent Bungion 的 MVVM Light

假设您正在使用 MVVM Light(如果您正在使用其他工具包,您可以从中推断)...

因此,要将其转换为 MVVM,您需要做一些事情。

  1. 创建定义的Models. 我通常使用 POCO,简单地定义模型的属性。这意味着抽象出您的数据访问层(更多内容见下文)。

  2. 创建您的ViewModel. 这是您在视图中绑定的属性的位置。你ObservableCollections会坐在这里。在这里初始化您创建的类的实例。对 DAL 层的调用将在此处进行。(例如,而不是在视图的构造函数中)。

    将其添加ViewModel到您的ViewModelLocator(我使用mvvmlocatorpropertyMVVM Light 中提供的代码片段)。

    View使用ViewModel绑定您的Locator。在您的 中UserControl,您可以在声明中添加如下内容:

    DataContext="{Binding YourViewModel, Source={StaticResource Locator}}"
    
    Run Code Online (Sandbox Code Playgroud)
  3. 我会听从布伦南·文森特的建议。我通常创建一个服务接口(注意:不是一个类,而是一个接口)来定义我的 DAL(数据访问层)将具有的方法。我这样做是为了实现可混合性,即设计时数据。如果您不熟悉接口,也许简单的 DAL 类就是一个很好的起点。然后,我使用依赖注入 (DI) 来注入 DAL 服务的实例。DI 非常简单 -ViewModelLocator您需要新建(实例化)您的 DAL 服务类并通过您的vm = New ViewModel(MyDALService dalService)调用传递它。显然,您还需要MyDALServiceViewModel构造函数中接受引用。EquipmentViewModel这是我参与的项目中的构造函数的示例:

    public EquipmentViewModel(Services.IEquipmentService equipmentService)
    {
        EquipmentService = equipmentService;
        LoadData();
    }
    
    Run Code Online (Sandbox Code Playgroud)

ViewModel接受类型的参数IEquipmentService(这是我的接口)。在该LoadData方法中,我调用EquipmentService.GetEquipment()触及数据库层的 DAL 方法。

有任何问题请告诉我。MVVM 可能很痛苦,但我很高兴我坚持了下来。祝你好运。:)