C# WPF将列表返回给类

C# WPF将列表返回给类,c#,wpf,C#,Wpf,对于VB web表单中的WPF和C#来说是个新手,所以对于这个结构糟糕的问题我很抱歉,我将根据需要补充以改进。我试图通过向MySQL添加数据库调用来实现一个示例,以填充随需应变树视图控件。这里是到示例代码的链接 数据库连接正常,数据正在填充数据集。我迭代以将其放入列表中。但似乎无法解决将列表传递给类以填充控件的问题 public class Level1 { public Level1(string level1Name) { this.Level1Name =

对于VB web表单中的WPF和C#来说是个新手,所以对于这个结构糟糕的问题我很抱歉,我将根据需要补充以改进。我试图通过向MySQL添加数据库调用来实现一个示例,以填充随需应变树视图控件。这里是到示例代码的链接

数据库连接正常,数据正在填充数据集。我迭代以将其放入列表中。但似乎无法解决将列表传递给类以填充控件的问题

public class Level1
{
    public Level1(string level1Name)
    {
        this.Level1Name = level1Name;
    }

    public string Level1Name { get; private set; }

    readonly List<Level2> _level2s = new List<Level2>();
    public List<Level2> Level2s
    {
        get { return _level2s; }
    }
}
试试下面这个

List L1=新列表();
foreach(级别1s中的var行)
{
Level1 L=新的Level1();
//L.Level1Name=row.ToString();此处根据需要添加项目
L1.加入(L);
}
返回L1.ToArray();
试试下面这个

List L1=新列表();
foreach(级别1s中的var行)
{
Level1 L=新的Level1();
//L.Level1Name=row.ToString();此处根据需要添加项目
L1.加入(L);
}
返回L1.ToArray();
试试下面这个

List L1=新列表();
foreach(级别1s中的var行)
{
Level1 L=新的Level1();
//L.Level1Name=row.ToString();此处根据需要添加项目
L1.加入(L);
}
返回L1.ToArray();
试试下面这个

List L1=新列表();
foreach(级别1s中的var行)
{
Level1 L=新的Level1();
//L.Level1Name=row.ToString();此处根据需要添加项目
L1.加入(L);
}
返回L1.ToArray();

您应该使用MVVM设计模式来解决这个问题。您的问题中列出的要求不多,因此我将假设我自己的要求,这将引导您走上正确的道路

首先要确定的是,在呈现
TreeView
之前,您的记录在运行时是否准备就绪/被提取,以及它们是否会在应用程序的生命周期中从结构中更改/更新/添加/删除。如果不改变结构,您可以继续使用
List
作为收藏。如果您(或用户)将要从集合中添加/删除,并最终更改结构,则需要通知UI集合发生了更改;因此,您可以使用内置的。这里是一个MVVM纯粹主义解决方案,假设您的数据将在应用程序启动时提取,并且您将修改集合:

注意
RelayCommand
的实现取自

模型
视图模型 模型提供者 MainWindow.xaml
您应该使用MVVM设计模式来解决这个问题。您的问题中列出的要求不多,因此我将假设我自己的要求,这将引导您走上正确的道路

首先要确定的是,在呈现
TreeView
之前,您的记录在运行时是否准备就绪/被提取,以及它们是否会在应用程序的生命周期中从结构中更改/更新/添加/删除。如果不改变结构,您可以继续使用
List
作为收藏。如果您(或用户)将要从集合中添加/删除,并最终更改结构,则需要通知UI集合发生了更改;因此,您可以使用内置的。这里是一个MVVM纯粹主义解决方案,假设您的数据将在应用程序启动时提取,并且您将修改集合:

注意
RelayCommand
的实现取自

模型
视图模型 模型提供者 MainWindow.xaml
您应该使用MVVM设计模式来解决这个问题。您的问题中列出的要求不多,因此我将假设我自己的要求,这将引导您走上正确的道路

首先要确定的是,在呈现
TreeView
之前,您的记录在运行时是否准备就绪/被提取,以及它们是否会在应用程序的生命周期中从结构中更改/更新/添加/删除。如果不改变结构,您可以继续使用
List
作为收藏。如果您(或用户)将要从集合中添加/删除,并最终更改结构,则需要通知UI集合发生了更改;因此,您可以使用内置的。这里是一个MVVM纯粹主义解决方案,假设您的数据将在应用程序启动时提取,并且您将修改集合:

注意
RelayCommand
的实现取自

模型
视图模型 模型提供者 MainWindow.xaml
您应该使用MVVM设计模式来解决这个问题。您的问题中列出的要求不多,因此我将假设我自己的要求,这将引导您走上正确的道路

第一件事是确定你的记录是否正确
List<string> level1s = new List<string>();
DataSet ds = new DataSet();

foreach (DataTable table in ds.Tables)
{
    foreach (DataRow row in table.Rows)
    {
        level1s.Add((string)row["name"]);
    }
}


**UPDATE**: Trying to return the list...

return new Level1[]
  {
  foreach(DataRow row in level1s)
  {
    // iterate here               
  }
};
using BusinessLib;

namespace TreeViewWithViewModelTOC.LoadOnDemand
{
    public class Level1ViewModel : TreeViewItemViewModel
    {
        readonly Level1 _level1;

        public Level1ViewModel(Level1 level1) 
            : base(null, true)
        {
            _level1 = level1;
        }

        public string Level1Name
        {
            get { return _level1.Level1Name; }
        }

        protected override void LoadChildren()
        {
            foreach (Level2 level2 in Database.GetLevel2s(_level1))
                base.Children.Add(new Level2ViewModel(level2, this));
        }
    } 
}
List<Level1> L1=new List<Level1>();
 foreach(var row in level1s)
 {
    Level1 L=new Level1();
    // L.Level1Name = row.ToString(); here add items as you need
    L1.Add(L);
  }
 return L1.ToArray();
public class First
{
    public string Name
    {
        get;
        set;
    }

    public readonly List<Second> Children;

    public First(string name)
    {
        Name = name;
        Children = new List<Second>
        {
            new Second(1),
            new Second(2),
            new Second(3),
        };
    }

    public void AddChild(Second child)
    {
        Children.Add(child);
        ChildAdded(this, new ChildAddedEventArgs(child));
    }

    public EventHandler<ChildAddedEventArgs> ChildAdded;
}
public class ChildAddedEventArgs //technically, not considered a model
{
    public readonly Second ChildAdded;
    public ChildAddedEventArgs(Second childAdded)
    {
        ChildAdded = childAdded;
    }
}
public class Second
{
    public int Number
    {
        get;
        set;
    }
    public Second(int number)
    {
        Number = number;
    }
}
public class MainViewModel : INotifyPropertyChanged
{
    private readonly ObservableCollection<FirstViewModel> _items;
    private readonly ICommand _addFirstFirstChildCommand;
    private readonly ICommand _addSecondFirstChildCommand;
    private readonly ICommand _toggleExpandCollapseCommand;

    private bool _firstAddedFlag;

    public MainViewModel(IEnumerable<First> records)
    {
        _items = new ObservableCollection<FirstViewModel>();
        foreach(var r in records)
        {
            _items.Add(new FirstViewModel(r));
        }

        _addFirstFirstChildCommand = new RelayCommand(param => AddFirst(), param => CanAddFirst);
        _addSecondFirstChildCommand = new RelayCommand(param => AddSecond(), param => CanAddSecond);
        _toggleExpandCollapseCommand = new RelayCommand(param => ExpandCollapseAll(), param =>
        {
            return true;
        });
    }

    public ObservableCollection<FirstViewModel> Items
    {
        get
        {
            return _items;
        }
    }

    public ICommand AddFirstFirstChildCommand
    {
        get
        {
            return _addFirstFirstChildCommand;
        }
    }
    public ICommand AddSecondFirstChildCommand
    {
        get
        {
            return _addSecondFirstChildCommand;
        }
    }

    public ICommand ToggleExpandCollapseCommand
    {
        get
        {
            return _toggleExpandCollapseCommand;
        }
    }
    public bool CanAddFirst
    {
        get
        {
            return true;
        }
    }

    public bool CanAddSecond
    {
        get
        {
            //Only allow second to be added if we added to first, first
            return _firstAddedFlag;
        }
    }

    public void AddFirstChild(FirstViewModel item)
    {
        Items.Add(item);
    }

    private void AddFirst()
    {
        _items[0].AddChild(new Second(10));
        _firstAddedFlag = true;
    }

    private void AddSecond()
    {
        _items[1].AddChild(new Second(20));
    }

    private void ExpandCollapseAll()
    {
        foreach(var i in Items)
        {
            i.IsExpanded = !i.IsExpanded;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
public class FirstViewModel : INotifyPropertyChanged
{
    private readonly First model;
    private readonly ObservableCollection<SecondViewModel> _children;

    private bool _isExpanded;

    public FirstViewModel(First first)
    {
        _children = new ObservableCollection<SecondViewModel>();
        model = first;
        foreach(var s in first.Children)
        {
            Children.Add(new SecondViewModel(s));
        }
        model.ChildAdded += OnChildAdded;
    }

    public string FirstName
    {
        get
        {
            return model.Name;
        }
        set
        {
            model.Name = value;
            NotifyPropertyChanged();
        }
    }

    public ObservableCollection<SecondViewModel> Children
    {
        get
        {
            return _children;
        }
    }

    public bool IsExpanded
    {
        get
        {
            return _isExpanded;
        }
        set
        {
            _isExpanded = value;
            NotifyPropertyChanged();
        }
    }

    internal void AddChild(Second second)
    {
        model.AddChild(second);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public void OnChildAdded(object sender, ChildAddedEventArgs args)
    {
        if(Children != null)
        {
            Children.Add(new SecondViewModel(args.ChildAdded));
        }
    }
}
public class SecondViewModel : INotifyPropertyChanged
{
    private readonly Second model;
    private bool _isExpanded;

    public SecondViewModel(Second second)
    {
        model = second;
    }
    public int SecondNumber
    {
        get
        {
            return model.Number;
        }
        set
        {
            model.Number = value;
            NotifyPropertyChanged();
        }
    }

    //Added property to avoid warnings in output window
    public bool IsExpanded
    {
        get
        {
            return _isExpanded;
        }
        set
        {
            _isExpanded = value;
            NotifyPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
public class Database
{
    public static IEnumerable<First> GetChildren()
    {
        List<First> firsts = new List<First>();
        firsts.Add(new First("John"));
        firsts.Add(new First("Roxanne"));
        return firsts;
    }
}
public partial class MainWindow : Window
{
    private MainViewModel mvm;

    public MainWindow()
    {
        var db = Database.GetChildren();
        mvm = new MainViewModel(db);
        InitializeComponent();

        DataContext = mvm;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        //Do not do this, example only
        var f = new First("Billy");
        mvm.AddFirstChild(new FirstViewModel(f));

        //Prove that the event was raised in First, FirstViewModel see & handles it, and
        //the UI is updated
        f.AddChild(new Second(int.MaxValue));
    }
}
<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication2"
        Title="MainWindow">
    <Grid>
        <TreeView ItemsSource="{Binding Items}">
            <TreeView.Resources>
                <HierarchicalDataTemplate DataType="{x:Type local:FirstViewModel}" 
                                          ItemsSource="{Binding Children}">
                    <TextBlock Text="{Binding FirstName}" />
                </HierarchicalDataTemplate>
                <DataTemplate DataType="{x:Type local:SecondViewModel}">
                    <TextBlock Text="{Binding SecondNumber}" />
                </DataTemplate>
            </TreeView.Resources>
            <TreeView.ItemContainerStyle>
                <Style TargetType="{x:Type TreeViewItem}">
                    <Setter Property="IsExpanded"
                            Value="{Binding IsExpanded, Mode=TwoWay}" />
                </Style>
            </TreeView.ItemContainerStyle>
        </TreeView>
        <StackPanel Orientation="Vertical"
                    VerticalAlignment="Bottom">
            <StackPanel Orientation="Horizontal">
                <Button Content="Add Child to first First"
                        Command="{Binding AddFirstFirstChildCommand}" />
                <Button Content="Toggle Expand"
                        Command="{Binding ToggleExpandCollapseCommand}" />
                <Button Content="Add Child to second First"
                        Command="{Binding AddSecondFirstChildCommand}" />
            </StackPanel>
            <Button Content="Bad Codebehind Button" 
                    Click="Button_Click"/>
        </StackPanel>
    </Grid>
</Window>
public void Level1[] GetLevels()
{
   DataSet ds = ....
   return ds.Tables[0].Rows
       .Select(row => new Level1((string)row["name"]))
       .ToArray();
}
public void Level1[] GetLevels()
{
   DataSet ds = ....
   return ds.Tables
       .SelectMany(t => t.Rows)
       .Select(row => new Level1((string)row["name"]))
       .ToArray();
}