c# - WPF:MVVM 中的 TreeView

标签 c# wpf xaml mvvm treeview

我有一个 TreeView,我(终于)能够使用数据绑定(bind)从数据库中填充它。

树中有 2 个对象:

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

目前我有一个模型- 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);
    }
}

报告项目:

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

最佳答案

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

假设您使用的是 MVVM Light(如果您使用的是其他工具包,则可以由此推断)...

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

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

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

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

    使用 Locator 将您的 View 绑定(bind)到 ViewModel。在您的 UserControl 中,您可以在声明中放置如下内容:

    DataContext="{Binding YourViewModel, Source={StaticResource Locator}}"
    
  3. 我会听从 Brennan Vincent 的建议。我通常会创建一个服务接口(interface)(注意:不是类,而是接口(interface))来定义我的 DAL(数据访问层)将具有的方法。我这样做是为了考虑到 Blendability,也就是设计时数据。如果您不熟悉接口(interface),也许简单的 DAL 类就是一个很好的开始方式。然后我使用依赖项注入(inject) (DI) 来注入(inject)我的 DAL 服务实例。 DI 非常简单 - 在 ViewModelLocator 中,您需要新建(实例化)您的 DAL 服务类并通过您的 vm = New ViewModel(MyDALService dalService) 调用传递它。显然,您还需要在 ViewModel 构造函数中接受一个 MyDALService 引用。下面是我参与的项目中的 EquipmentViewModel 构造函数示例:

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

ViewModel 接受 IEquipmentService 类型的参数(这是我的接口(interface))。在 LoadData 方法中,我调用了我的 DAL 的 EquipmentService.GetEquipment() 方法来访问我的数据库层。

有问题可以私信我。 MVVM 可能会很痛苦,但我很高兴我坚持了下来。 祝你好运。 :)

关于c# - WPF:MVVM 中的 TreeView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6443448/

相关文章:

c# - 如何从 XAML 中的静态成员引用属性?

c# - 管理为移动游戏对象而创建的 Vector3 的内存

c# - Facebook C# SDK授权问题

c# - 烦恼! POST 在 HttpWebRequest 中返回 302 发现对象移动错误

c# - WPF工具包图表: How to add value label to specific data point

wpf - 获取 ItemsControl 中的选定项目

WPF 简单的技巧和窍门?

c# - Unity3d 在构建后看不到项目文件夹中的 XML 文件

c# - WPF 应用程序在某些机器上不起作用 : Stopped working error

c# - .Net 4.5 中的 Microsoft.Windows.Shell 命名空间等效项