数据绑定一个的ObservableCollection< T>在MVVM [英] Databinding a ObservableCollection<T> in MVVM

查看:104
本文介绍了数据绑定一个的ObservableCollection< T>在MVVM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个DataTemplate持有的电影列表的ListView控件。据databinded到ObservableColection但每当我编辑Movie.Name即使名称叫我PropertyChangedEventHandler被称为与名不更新ListView控件。

我加2电影s到我的收藏在我的初始化,这些都是正确的显示(Klovn电影,两者)

所以,当我点击编辑应该改变所选电影的文本,并改变它的名称为测试,是的的改变,但变化不会在ListView,但如果显示我输出收集在foreach然后命名为Test。

View.xaml

<窗​​口x:类=MovieDB3.MainWindow         的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/$p$psentation         的xmlns:X =htt​​p://schemas.microsoft.com/winfx/2006/xaml         标题=主窗口高度=350宽度=525>     < D​​ockPanel中>         <菜单DockPanel.Dock =评出的>             <菜单项标题=文件>                 <菜单项标题=编辑点击=MenuEditClick/>             < /菜单项>         < /菜单>         <电网DockPanel.Dock =评出的>             < Grid.ColumnDefinitions>                 < ColumnDefinition />                 < ColumnDefinition />             < /Grid.ColumnDefinitions>             < Grid.RowDefinitions>                 < RowDefinition />             < /Grid.RowDefinitions>             < ListView控件VerticalAlignment =拉伸NAME =ListViewMovies的ItemsSource ={绑定路径=集}IsSynchronizedWithCurrentItem =真>                 < ListView.ItemTemplate>                     <的DataTemplate>                         < WrapPanel中>                             < TextBlock的文本={绑定路径=名}/>                         < / WrapPanel中>                     < / DataTemplate中>                 < /ListView.ItemTemplate>             < / ListView控件>         < /网格>     < / DockPanel中> < /窗>

View.cs

 使用系统;
使用System.Windows;
使用MovieDB3.Models;
使用MovieDB3.ViewModels;

命名空间MovieDB3
{
    ///<总结>
    ///为MainWindow.xaml交互逻辑
    ///< /总结>
    公共部分类主窗口:窗口
    {
        私人MainViewModel MVM;
        公共主窗口()
        {
            的InitializeComponent();
            MVM =新MainViewModel();
            的DataContext = MVM;
        }

        私人无效MenuEditClick(对象发件人,RoutedEventArgs E)
        {
            MVM.setMovieName((电影)ListViewMovies.SelectedItem,测试);
        }
    }
}
 

视图模型

 使用系统;
使用System.ComponentModel;
使用MovieDB3.Models;
使用System.Collections.ObjectModel;

命名空间MovieDB3.ViewModels
{
    类MainViewModel:INotifyPropertyChanged的
    {
        公众的ObservableCollection<电影>集合{获得;组;}

        公共MainViewModel()
        {
            集合=新的ObservableCollection<电影>();

            //测试KODE
            动画电影=新电影();
            movie.Name =Klovn电影;
            Collection.Add(电影);
            电影=新电影();
            movie.Name =摘自;
            Collection.Add(电影);
        }

        公共无效setMovieName(动画电影,串了newName)
        {
            //movie.Name =了newName;
            Console.WriteLine(CurrentName:+ movie.Name);
            INT I = Collection.IndexOf(电影);
            收藏[我] .Name点=了newName;
            Console.WriteLine(新名称:+ movie.Name);
            NotifyPropertyChanged(姓名);
        }

        公共无效setMovieName(字符串currentName,串了newName)
        {
            的foreach(在收集电影短片)
            {
                如果(movie.Name.Equals(currentName))
                {
                    movie.Name =了newName;
                    NotifyPropertyChanged(姓名);
                    返回;
                }
            }
        }

        //公共字符串的movieName
        // {
        //    组
        // {

        // NotifyPropertyChanged(电影名称);
        //}
        //}

        公共事件PropertyChangedEventHandler的PropertyChanged;

        私人无效NotifyPropertyChanged(字符串信息)
        {
            如果(的PropertyChanged!= NULL)
            {
                的PropertyChanged(这一点,新PropertyChangedEventArgs(信息));
            }
        }
    }
}
 

Movie.cs

 使用系统;

命名空间MovieDB3.Models
{
    一流的电影
    {
        公共字符串名称{;组; }
        公众诠释编号{获得;组; }
        公共双评级{获得;组; }
        公开发行的日期时间{获得;组; }
        公开时间跨度运行{获得;组; }
        公共字符串拖车{获得;组; }
    }
}
 

解决方案

INotifyPropertyChanged的需要在Movie类来实现,也避免了手动引发事件。 (现在你告诉认为,视图模型的名称属性改变,这不存在)


你的类可能看起来是这样的:

 公共类的电影:INotifyPropertyChanged的
{
    私人字符串_name =的String.Empty;
    公共字符串名称
    {
        {返回_name; }
        组
        {
            如果(_name!=值)
            {
                _name =价值;
                NotifyPropertyChanged(姓名);
            }
        }
    }

    //...All其它性能(以同样的方式)...

    公共事件PropertyChangedEventHandler的PropertyChanged;

    公共无效NotifyPropertyChanged(字符串propertyName的)
    {
        如果(的PropertyChanged!= NULL)
        {
            的PropertyChanged(这一点,新PropertyChangedEventArgs(propertyName的));
        }
    }
}
 

你的改变方法减少到:

 公共无效setMovieName(动画电影,串了newName)
    {
        Console.WriteLine(CurrentName:+ movie.Name);
        movie.Name =了newName; //通知现在的setter方法​​自动提升在电影类
        Console.WriteLine(新名称:+ movie.Name);
    }
 

I have a ListView with a Datatemplate that holds a list of Movies. It is databinded to a ObservableColection but whenever I edit the Movie.Name it does not update the ListView even though "Name" is called in my PropertyChangedEventHandler is called with "Name".

I add 2 "Movie"s to my collection in my initializer and these are shown correct (Klovn the Movie, Taken)

So when I click Edit it should change the text of the selected movie and change the Name of it to "Test" and is is changed but the change is not shown in the ListView but if I output Collection with a foreach then Name is Test.

View.xaml

<Window x:Class="MovieDB3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="File">
                <MenuItem Header="Edit" Click="MenuEditClick"/>
            </MenuItem>
        </Menu>
        <Grid DockPanel.Dock="Top">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <ListView VerticalAlignment="Stretch" Name="ListViewMovies" ItemsSource="{Binding Path=Collection}" IsSynchronizedWithCurrentItem="True" >
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <WrapPanel>
                            <TextBlock Text="{Binding Path=Name}"/>
                        </WrapPanel>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </Grid>
    </DockPanel>
</Window>

View.cs

using System;
using System.Windows;
using MovieDB3.Models;
using MovieDB3.ViewModels;

namespace MovieDB3
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private MainViewModel MVM;
        public MainWindow()
        {
            InitializeComponent();
            MVM = new MainViewModel();
            DataContext = MVM;
        }

        private void MenuEditClick(object sender, RoutedEventArgs e)
        {
            MVM.setMovieName((Movie)ListViewMovies.SelectedItem, "test");
        }
    }
}

The ViewModel

using System;
using System.ComponentModel;
using MovieDB3.Models;
using System.Collections.ObjectModel;

namespace MovieDB3.ViewModels
{
    class MainViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<Movie> Collection {get; set;}

        public MainViewModel()
        {
            Collection = new ObservableCollection<Movie>();

            //Test kode
            Movie movie = new Movie();
            movie.Name = "Klovn The Movie";
            Collection.Add(movie);
            movie = new Movie();
            movie.Name = "Taken";
            Collection.Add(movie);
        }

        public void setMovieName(Movie movie, string newName)
        {
            //movie.Name = newName;
            Console.WriteLine("CurrentName: " + movie.Name);
            int i = Collection.IndexOf(movie);
            Collection[i].Name = newName;
            Console.WriteLine("NewName: " + movie.Name);
            NotifyPropertyChanged("Name");
        }

        public void setMovieName(string currentName, string newName)
        {
            foreach (Movie movie in Collection)
            {
                if (movie.Name.Equals(currentName))
                {
                    movie.Name = newName;
                    NotifyPropertyChanged("Name");
                    return;
                }
            }
        }

        //public string MovieName
        //{
        //    set 
        //    {

        //        NotifyPropertyChanged("MovieName");
        //    }
        //}

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }
}

Movie.cs

using System;

namespace MovieDB3.Models
{
    class Movie
    {
        public string Name { get; set; }
        public int Id { get; set; }
        public double Rating { get; set; }
        public DateTime Release { get; set; }
        public TimeSpan Runtime { get; set; }
        public String Trailer { get; set; }
    }
}

解决方案

INotifyPropertyChanged needs to be Implemented in your Movie class, also avoid raising the event manually. (Right now you are telling the View that the ViewModel's property "Name" changed, which does not exist)


What your class might look like:

public class Movie : INotifyPropertyChanged
{
    private string _name = String.Empty;
    public string Name
    {
        get { return _name; }
        set
        {
            if (_name != value)
            {
                _name = value;
                NotifyPropertyChanged("Name");
            }
        }
    }

    //...All the other properties (the same way)...

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

What your changing method is reduced to:

    public void setMovieName(Movie movie, string newName)
    {
        Console.WriteLine("CurrentName: " + movie.Name);
        movie.Name = newName; //The notification is now raised automatically in the setter of the property in the movie class
        Console.WriteLine("NewName: " + movie.Name);
    }

这篇关于数据绑定一个的ObservableCollection&LT; T&GT;在MVVM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆