Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF:MVVM中的TreeView_C#_Wpf_Xaml_Mvvm_Treeview - Fatal编程技术网

C# WPF:MVVM中的TreeView

C# WPF:MVVM中的TreeView,c#,wpf,xaml,mvvm,treeview,C#,Wpf,Xaml,Mvvm,Treeview,我有一个TreeView,我(终于)能够使用数据绑定从数据库中填充它 树中有两个对象: FavoriteFolder-可以有子对象的对象:文件夹或报表 FavoriteReport-不能有任何子对象的对象:当用户单击此项时,它将运行一个报告 目前,我有一个模型视图类型设置(我想),我想将其更改为MVVM,这样我就可以使用TreeView-项,而不是简单地显示它们 我已经看过很多例子,但我对MVVM和WPF还是比较陌生,所以对于我的具体例子的任何指导都将不胜感激 TreeView中存在的两个类

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

树中有两个对象:

  • FavoriteFolder-可以有子对象的对象:文件夹或报表
  • FavoriteReport-不能有任何子对象的对象:当用户单击此项时,它将运行一个报告
目前,我有一个模型视图类型设置(我想),我想将其更改为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);
    }
}
以及main window.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;
    }
}
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
ObservableCollection items=新的ObservableCollection();
FavoriteFolder fdr=新的FavoriteFolder();
fdr.FolderID=“0”;
项目=fdr.儿童;
this.DataContext=项目;
}
}

我的第一个建议是加入一个MVVM工具包,因为它比自己做任何事情都要容易(例如,实现
INotifyPropertyChanged
接口)。我用

假设您使用的是MVVM Light(如果您使用的是另一个工具包,则可以从中推断)

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

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

  • 创建您的
    视图模型
    。在这里,您将在您的面纱中拥有您要绑定到的属性。您的
    可观察集合将位于此处。初始化您创建的类的实例将转到这里。对DAL层的调用将转到此处。(例如,而不是在视图的构造函数中)

    将此
    ViewModel
    添加到您的
    viewmodelocator
    (我使用mvvmlight中提供的
    mvvmlocatorproperty
    代码片段)

    使用
    定位器将
    视图
    绑定到
    视图模型
    。在
    UserControl
    中,您可以在声明中添加如下内容:

    DataContext="{Binding YourViewModel, Source={StaticResource Locator}}"
    
  • 我会听从布伦南·文森特的建议。我通常创建一个服务接口(注意:不是一个类,而是一个接口),它定义了我的DAL(数据访问层)将拥有的方法。我这样做是为了考虑可混合性,也就是设计时数据。如果您不熟悉接口,那么简单地使用DAL类可能是一个很好的开始。然后,我使用依赖注入(DI)注入DAL服务的一个实例。DI非常简单-在
    ViewModelLocator
    中,您需要新建(实例化)DAL服务类,并通过
    vm=newViewModel(MyDALService-dalService)
    调用传递它。显然,您还需要在
    ViewModel
    构造函数中接受
    MyDALService
    引用。下面是我的
    EquipmentViewModel
    构造器在我参与的项目中的一个示例:

    public EquipmentViewModel(Services.IEquipmentService equipmentService)
    {
        EquipmentService = equipmentService;
        LoadData();
    }
    
  • ViewModel
    接受
    IEquipmentService
    类型的参数(这是我的界面)。在
    LoadData
    方法中,我调用到达数据库层的DAL的
    EquipmentService.GetEquipment()
    方法

    任何问题都让我知道。MVVM可能是一种痛苦,但我很高兴我能坚持下去。
    祝你好运

    Josh Smith给出了关于如何使用的明确描述,我无法补充更多内容。

    我也不是设计专家,但将数据访问逻辑与模型分离不是很有意义吗?我同意,你认为创建一个单独的类来连接数据库,它有返回子元素的方法吗;模型。假设我有一个包含
    Foo
    集合的模型。现在我想将集合绑定到我的UI控件,那么,我必须在我的ViewModel中创建另一个集合,并使其与模型的集合保持同步?希望我遗漏了一些东西,因为我觉得这很可笑。为什么你会有一个只有
    Foo
    集合的模型?创建一个名为
    Foo
    (也称为Foo的单个实例,而不是集合)的模型,然后在视图模型中,在那里新建一个
    Foo
    类的集合。显然,这就是一个示例。。。好的,我有一个带有id的模型,一个Foo集合,还有一个字符串名称。这有用吗?你的例子和我问的例子在语义上是不同的。你能想象一个包含集合类型的模型吗?它确实适用于任何类型。我看不出有一个模型和一个ViewModel的目的,它本质上模仿了所有这些属性,并为视图提供了PropertyChanged通知。就像我说的,我肯定错过了什么,因为那只是。。。哑巴,当然。。我有里面有收藏的模型。我实现了IEditableObject来处理模型上的更改跟踪。假设我在我的
    Bar
    模型中有一组
    Foo
    s。我在我的虚拟机中创建了一个
    的集合(例如,可观察的集合条)。如果我有一个网格想要绑定到我的
    Foo
    s,我只需要将它绑定到bar.Foo。我不会在视图模型中创建新的Foo集合。那将是荒谬和愚蠢的。是的,是的,它将是。因此,在本例中,您只需公开模型对象并绑定到它,因此它们需要发出属性更改通知,而不是VM本身。我想我根本不认为需要一个模型。我可以将所有这些数据都放在我的虚拟机中,并将UI绑定到它,虚拟机将是respo
    public EquipmentViewModel(Services.IEquipmentService equipmentService)
    {
        EquipmentService = equipmentService;
        LoadData();
    }