MVVM 树状视图 wpf(绑定?)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21311858/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 10:35:08  来源:igfitidea点击:

MVVM treeview wpf(binding?)

c#wpfmvvmtreeview

提问by curiousity

Sorry for noob question. Perhaps this is not a question - but I need a tutorial sample/ I am trying to write a model task to get "handy" with mvvm pattern in wpf. I am decide to write something like librarian helper. That is one simple wpf window with one combobox(for selecting if the book is fantasy or sf), textbox (for book name input), button Add, and a treeview with a tree like:

对不起,菜鸟问题。也许这不是问题 - 但我需要一个教程示例/我正在尝试编写一个模型任务,以便在 wpf 中使用 mvvm 模式“得心应手”。我决定写一些类似图书管理员助手的东西。那是一个简单的 wpf 窗口,带有一个组合框(用于选择这本书是幻想书还是科幻书)、文本框(用于书名输入)、按钮添加和一个树状视图,例如:

 Books
  ------>ScienceFic
        ----->bookName1
        ----->bookName2
  ------->Fantasy
        ------>bookName3

And I have some difficulties with binding and separation view model from view. Could You help me?

而且我在绑定和分离视图模型方面遇到了一些困难。你可以帮帮我吗?

public enum LibraryType
{
    ScienceFic,
    Fantasy
}
    Class Model: INotifyPropertyChanged
    {
     private int bookId;
     private string bookName;
     private LibraryType bookType;
     public event PropertyChangedEventHandler PropertyChanged;
        //....and for all this fields  I have used a INotifyPropertyChanged as 
    /*
    http://stackoverflow.com/questions/1315621/implementing-inotifypropertychanged-does-a-better-way-exist
    */
    }

At this point the MODEL is finished I think.

在这一点上,我认为 MODEL 已经完成了。

Now about VIEW: I have simply open editor of MainWindow and manually added button, textbox, combobox, and a treeview. After addition of

现在关于 VIEW:我只需打开 MainWindow 编辑器并手动添加按钮、文本框、组合框和树视图。添加后

comboBox1.ItemsSource = Enum.GetValues(typeof(LibraryType)).Cast<LibraryType>();
 comboBox1.SelectedIndex = 0;

I have initialized my combo with right types of books))) But((, I have done this in code, not in XAML - is this right for MVVM Binding? (first question) Next, I have bind (as I suppose) my textBox text to current book name property in ViewModel (I have done this in XAML like this):

我已经用正确类型的书籍初始化了我的组合)))但是((,我已经在代码中完成了这个,而不是在 XAML 中 - 这是否适合 MVVM 绑定?(第一个问题)接下来,我已经绑定(我想)我的文本框文本到 ViewModel 中的当前书名属性(我已经在 XAML 中这样做了):

 <TextBox Text="{Binding Path=CurrentBookName}"/>

is this right? (second question)

这是正确的吗?(第二个问题)

And, finally, VIEWMODEL

最后,VIEWMODEL

 Class ViewModel
{
  private string currentBookName;
  private LibraryType selectedBookType;
  public event PropertyChangedEventHandler PropertyChanged;
  //also properties and  OnPropertyChanged/SetField functions like in Model class

  //and finally I have created two lists for book storing
  private List<Model> sfStorage = new List<Model>();
  private List<Model> fantasyStorage = new List<Model>();
  //and simple getters for this two lists, like:
  public List<Model> GetSFStorage
  {
   get{return this.sfStorage;}
  }
  //and a simple function for addition of new books
  //that I plan to call when AddButton pressed
  public void Addition(???)
        {
            if (!string.IsNullOrEmpty(currentBookName))
            {
                //? I have add CurrentBookName in XAML of View (see above)
                //?but is it enough to have a property of CurrentBookType
                //to grant that a valide value from combobox will be here?
                var modelNewBook = new Model(CurrentBookName,CurrentBookType);
                switch (selectedBookType)
                {
                    case LibraryType.ScienceFic:
                        sfStorage.Add(modelNewBook);
                        break;
                    case LibraryType.Fantasy:
                        fantasyStorage.Add(modelNewBook);
                        break;
                    default:
                        return;
                }
            }
}

Now I am only few step out of success (may be) BUT, how I could connect a treeView with this two lists in xaml or in code And how could I call Addition function when an Addbutton pressed (third and main question)? Perhaps, this is noob question, but I really need an sample. And, (perhaps) this question will be helpfull for others who try to understand MVVM and binding.

现在我离成功只有几步之遥(可能是)但是,我如何在 xaml 或代码中将 treeView 与这两个列表连接起来以及如何在按下 Addbutton 时调用 Addition 函数(第三个也是主要问题)?也许,这是菜鸟问题,但我真的需要一个样本。而且,(也许)这个问题对其他试图理解 MVVM 和绑定的人会有所帮助。

回答by Sukram

The following code is a quick hack of your application. I also understood that you have problems with the treeview so i only display the code passanges to the treeview and i fill my books list inside the constructor of my view model to have some data

以下代码是对您的应用程序的快速破解。我也知道你有树视图的问题,所以我只向树视图显示代码通道,我在视图模型的构造函数中填充我的书籍列表以获取一些数据

Model:

模型:

internal class Book : NotifyPropertyChangedBase
{
    private string name;
    private BookType type;
    public BookType Type
    {
       get => this.type;
    }
    set
    {
        this.SetProperty( ref this.type,value );
    }
}

public string Name
{
    get => return this.name;
    set
    {
        this.SetProperty( ref this.name,value );
    }
}

ViewModel:

视图模型:

private readonly List<Book> books;

public MainViewModel( )
{
    this.books = new List<Book>
    {
        new Book
        {
            Name = "Book 1",
            Type = BookType.Fantasy
        },
        new Book
        {
            Name = "Book 2",
            Type = BookType.Fantasy
        },
        new Book
        {
            Name = "Book 3",
            Type = BookType.Fantasy
        },
        new Book
        {
            Name = "Book 4",
            Type = BookType.SciFi
        }
    };
}

public ICollectionView Books
{
    get
    {
        var source = CollectionViewSource.GetDefaultView( this.books );
        source.GroupDescriptions.Add( new PropertyGroupDescription( "Type" ) 
    );
    return source;
}

View:

看法:

<TreeView ItemsSource="{Binding Books.Groups}">
  <TreeView.ItemTemplate>
    <HierarchicalDataTemplate ItemsSource="{Binding Items}">
      <TextBlock Text="{Binding Name}" />
    </HierarchicalDataTemplate>
  </TreeView.ItemTemplate>
</TreeView>

回答by deloreyk

From what I understand you need help generating the hierarchy in TreeViewusing a ViewModel. Todo this you will be using a HierarchicalDataTemplate. Your ViewModelwill require a collection of children, and you will use the simply bind the ItemsSourceproperty of the HierarchicalDataTemplateto that collection.

据我了解,您需要帮助生成TreeView使用ViewModel. 为此,您将使用HierarchicalDataTemplate. 您ViewModel将需要一个孩子的集合,并且您将使用简单的将 的ItemsSource属性绑定HierarchicalDataTemplate到该集合。

Take a look at this simple example someone made: TreeView and HierarchicalDataTemplate, Step-by-Step

看一下某人制作的这个简单示例:TreeView and HierarchicalDataTemplate, Step-by-Step