将新数据添加到ObservableCollection并使用MVVM模式绑定到ListView [英] Add new data to ObservableCollection and bind to ListView using MVVM pattern

查看:103
本文介绍了将新数据添加到ObservableCollection并使用MVVM模式绑定到ListView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用Wpf应用程序中的ObservableCollection在ListView控件中显示数据时遇到问题。我将2个文本框绑定到PPerson对象(其中包含Fname和LName属性 - 也是未绑定到任何文本框的FullName属性)。当
我将PPerson对象添加到Persons ObservableCollection时,Listview(和observableCollection对象)中的所有Fname和LName列都将更新为2个文本框中的新值。 如何使用
新值来阻止先前的行更新? 我似乎没有FullName 列的问题 - 只有Fname和LName 列,Fname和LName属性绑定到2个文本框。 另外,我在应用启动时在
的构造函数中添加了2个PPersons PersonViewModel。 这2个PPersons的Fname和LName没有使用2个文本框中的新值进行更新。 


我在下面显示了我的所有代码。 我假设每次在文本框中添加新值时都需要创建一个新的PPerson对象,但我该怎么做?


- Person.cs

使用System; 
使用System.Collections.Generic;
使用System.Linq;
使用System.Text;
使用System.Threading.Tasks;

namespace Wpf_tmp.Model
{
public class Person
{
private string fName;
公共字符串Fname
{
get {return fName; }
设置
{
fName = value;
}
}

private string lName;
public string LName
{
get {return lName; }
设置
{
lName = value;
}
}

private string fullName;
public string FullName
{
get
{
return fullName = Fname +" " + LName;
}
设置
{
if(fullName!= value)
{
fullName = value;
}
}
}
}
}

- PersonViewModel.cs

使用System; 
使用System.Collections.Generic;
使用System.Collections.ObjectModel;
使用System.Linq;
使用System.Text;
使用System.Threading.Tasks;
使用System.Windows.Input;
使用Wpf_tmp.Model;

namespace Wpf_tmp.ViewModel
{
public class PersonViewModel:ObservableObject
{
private Person _person;
public person PPerson
{
get
{
return _person;
}
设定
{
_person = value;
// OnPropertyChanged(" Person");
}
}

private ObservableCollection< Person> _persons;
public ObservableCollection< Person>人
{
获得
{
返回_persons;
}
设定
{
_persons = value;
// OnPropertyChanged(" Persons");
}
}

private ICommand _submitCommand;
public ICommand SubmitCommand
{
get
{
if(_submitCommand == null)
{
_submitCommand = new RelayCommand(SubmitExecute,CanSubmitExecute ,假);
}
return _submitCommand;
}
}

public PersonViewModel()
{
PPerson = new Person();
Persons = new ObservableCollection< Person>(){
new Person {Fname =" joe",LName =" smith"}
};
人物p =新人{Fname =" steve",LName =" bank" };
Persons.Add(p);
}

public void SubmitExecute(object parameter)
{
Persons.Add(PPerson);
// Person p = new Person();
//p.Fname = PPerson.Fname; // - 这些值全部更新整个ListView
//p.LName = PPerson.LName; // - 除了原来的PPersons
//Persons.Add(p);
}

private bool CanSubmitExecute(object parameter)
{
if(string.IsNullOrEmpty(PPerson.Fname)|| string.IsNullOrEmpty(PPerson.LName))
{
返回true; // - 这是另一个问题 - 所以我现在设置为true - 应该是false
}
else
{
return true;
}
}
}
}

- ObservalbeObject.cs

使用System; 
使用System.Collections.Generic;
使用System.Linq;
使用System.Text;
使用System.Threading.Tasks;使用System.ComponentModel
;使用System.Runtime.CompilerServices
;


名称空间Wpf_tmp
{
公共类ObservableObject:INotifyPropertyChanged
{
公共事件PropertyChangedEventHandler PropertyChanged;

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

- RelayCommand

 

使用System;
使用System.Collections.Generic;
使用System.Linq;
使用System.Text;
使用System.Threading.Tasks;
使用System.Windows.Input;

名称空间Wpf_tmp
{
公共类RelayCommand:ICommand
{
readonly Action< object> _执行;
readonly Func< object,bool> _canExecute;
bool canExecuteCache;

public RelayCommand(Action< object> execute,Func< object,bool> canExecute,bool CanExecuteCache)
{
_execute = execute;
_canExecute = canExecute;
canExecuteCache = CanExecuteCache;
}
公共事件EventHandler CanExecuteChanged
{
add {CommandManager.RequerySuggested + = value; }
remove {CommandManager.RequerySuggested - = value; }
}

public bool CanExecute(object parameter)
{
return _canExecute == null? true:_canExecute(parameter);
}

public void执行(对象参数)
{
_execute(parameter);
}
}
}

- MainWindow.xaml

< Window x:Class =" Wpf_tmp.MainWindow" 
xmlns =" http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x =" http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local =" clr-namespace:Wpf_tmp"
xmlns:vm =" clr-namespace:Wpf_tmp.ViewModel"
Title =" MainWindow"高度= QUOT; 350"宽度= QUOT; 525">

< Window.Resources>
< vm:PersonViewModel x:Key =" pvModel" />
< /Window.Resources>
< Grid DataContext =" {Binding Source = {StaticResource pvModel}}">
< Grid.RowDefinitions>
< RowDefinition Height =" Auto" />
< RowDefinition Height =" Auto" />
< RowDefinition Height =" Auto" />
< RowDefinition Height =" Auto" />
< RowDefinition Height =" *" />
< /Grid.RowDefinitions>
< Grid.ColumnDefinitions>
< ColumnDefinition Width =" Auto" />
< ColumnDefinition Width =" *" />
< /Grid.ColumnDefinitions>
< TextBlock Grid.Row =" 0" Grid.Column = QUOT; 0" Text =" First Name"的Horizo​​ntalAlignment = QUOT;中心" />
< TextBox Grid.Row =" 0" Grid.Column = QUOT 1 QUOT;宽度= QUOT; 100"的Horizo​​ntalAlignment = QUOT;中心" Text =" {Binding PPerson.Fname,Mode = TwoWay}" />
< TextBlock Grid.Row =" 1" Grid.Column = QUOT; 0" Text =" Last Name"的Horizo​​ntalAlignment = QUOT;中心" />
< TextBox Grid.Row =" 1" Grid.Column = QUOT 1 QUOT;宽度= QUOT; 100"的Horizo​​ntalAlignment = QUOT;中心" Text =" {Binding PPerson.LName,Mode = TwoWay}" />
< Button Content ="提交" Command =" {Binding SubmitCommand}"的Horizo​​ntalAlignment = QUOT;中心" Grid.Row = QUOT; 2英寸Grid.Column = QUOT; 0" />
< ListView ItemsSource =" {Binding Persons}" Grid.Row = QUOT; 3英寸Grid.Column = QUOT 1 QUOT;宽度= QUOT;自动">
< ListView.View>
< GridView>
< GridViewColumn Header =" First Name" DisplayMemberBinding =" {Binding Fname}"宽度= QUOT;自动" />
< GridViewColumn Header =" Last Name" DisplayMemberBinding =" {Binding LName}"宽度= QUOT;自动" />
< GridViewColumn Header =" Full Name" DisplayMemberBinding =" {Binding FullName}"宽度= QUOT;自动" />
< / GridView>
< /ListView.View>
< / ListView>
< / Grid>
< / Window>








Rich P

解决方案

好吧,我有一个解决方法 - 我在Person类中添加了另外两个属性,它们从原始的Fname和LName属性中获取它们的值。  ;我调用这些FFName和LLName,然后将它们绑定到Listview。 现在这些
未绑定到2个文本框的属性不会更新。 


我不确定这是不是一个好习惯,但我会把它放在那里以寻求改进建议。


这是我的新手Person.cs

使用System; 
使用System.Collections.Generic;
使用System.Linq;
使用System.Text;
使用System.Threading.Tasks;

namespace Wpf_tmp.Model
{
public class Person
{
private string fName;
公共字符串Fname
{
get {return fName; }
设置
{
fName = value;
}
}

private string lName;
public string LName
{
get {return lName; }
设置
{
lName = value;
}
}

private string fullName;
public string FullName
{
get
{
return fullName = Fname +" " + LName;
}
设置
{
if(fullName!= value)
{
fullName = value;
}
}
}

private string ffName;
public string FFName
{
get
{
return ffName = Fname;
}
设置
{
if(ffName!= Fname)
{
ffName = Fname;
}
}
}

private string llName;
public string LLName
{
get
{
return llName = LName;
}
设置
{
if(llName!= LName)
{
llName = LName;
}
}
}
}
}


I am having a problem displaying data in a ListView control from an ObservableCollection in my Wpf app. I bind 2 textboxes to a PPerson object (which contains Fname and LName properties -- also a FullName property which is not bound to any textbox). When I add the PPerson object to the Persons ObservableCollection all of the Fname and LName columns in the Listview (and observableCollection object) are updated to the new values from the 2 textboxes.  How can I prevent the prior rows from updating with the new values?  I don't seem to have the problem with the FullName column -- only the Fname and LName columns which the Fname and LName properties are bound to the 2 textboxes.  Also, I added 2 PPersons in the constructor of the PersonViewModel on app startup.  The Fname and LName of these 2 PPersons does not get updated with the new values from the 2 textboxes. 

I show all my code below.  I presume that I need to create a new PPerson object each time I add new values in the textboxes, but where do I do this?

--Person.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Wpf_tmp.Model
{
    public class Person
    {
        private string fName;
        public string Fname 
        {
            get { return fName; }
            set 
            { 
                fName = value;  
            }
        }

        private string lName;
        public string LName 
        {
            get { return lName; }
            set 
            { 
                lName = value; 
            }
        }

        private string fullName;
        public string   FullName
        {
            get
            {
                return fullName = Fname + " " + LName;                
            }
            set
            {
                if (fullName != value)
                {
                    fullName = value;
                }
            }
        }
    }
}

--PersonViewModel.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Wpf_tmp.Model;

namespace Wpf_tmp.ViewModel
{
    public class PersonViewModel : ObservableObject
    {
        private Person _person;
        public Person PPerson
        {
            get 
            { 
                return _person; 
            }
            set 
            { 
                _person = value; 
                //OnPropertyChanged("Person"); 
            }
        } 

        private ObservableCollection<Person> _persons;
        public ObservableCollection<Person> Persons
        {
            get 
            { 
                return _persons; 
            }
            set 
            { 
                _persons = value;
                //OnPropertyChanged("Persons");
            }
        }

        private ICommand _submitCommand;
        public ICommand SubmitCommand
        {
            get
            {
                if (_submitCommand == null)
                {
                    _submitCommand = new RelayCommand(SubmitExecute, CanSubmitExecute, false);
                }
                return _submitCommand;
            }
        }

        public PersonViewModel()
        {
            PPerson = new Person();
            Persons = new ObservableCollection<Person>(){
                new Person { Fname = "joe", LName = "smith"}
                };
            Person p = new Person { Fname = "steve", LName = "banks" };
            Persons.Add(p);
        }

        public void SubmitExecute(object parameter)
        {            
            Persons.Add(PPerson);
            //Person p = new Person();
            //p.Fname = PPerson.Fname;  //--these values all update the entire ListView
            //p.LName = PPerson.LName;  //--except for the original to PPersons
            //Persons.Add(p);
        }

        private bool CanSubmitExecute(object parameter)
        {
            if (string.IsNullOrEmpty(PPerson.Fname) || string.IsNullOrEmpty(PPerson.LName))
            {
                return true;  //--this is another problem -- so I just set to true for now -- should be false
            }
            else
            {
                return true;
            }
        }
    }
}

--ObservalbeObject.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Runtime.CompilerServices;


namespace Wpf_tmp
{
    public class ObservableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

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

--RelayCommand

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input; namespace Wpf_tmp { public class RelayCommand : ICommand { readonly Action<object> _execute; readonly Func<object, bool> _canExecute; bool canExecuteCache; public RelayCommand(Action<object> execute, Func<object, bool> canExecute, bool CanExecuteCache) { _execute = execute; _canExecute = canExecute; canExecuteCache = CanExecuteCache; } public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object parameter) { return _canExecute == null ? true : _canExecute(parameter); } public void Execute(object parameter) { _execute(parameter); } } }

--MainWindow.xaml

<Window x:Class="Wpf_tmp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Wpf_tmp"
        xmlns:vm="clr-namespace:Wpf_tmp.ViewModel"
        Title="MainWindow" Height="350" Width="525">
    
    <Window.Resources>
        <vm:PersonViewModel x:Key="pvModel" />
    </Window.Resources>
    <Grid DataContext="{Binding Source={StaticResource pvModel}}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions> 
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Row="0" Grid.Column="0" Text="First Name" HorizontalAlignment="Center"/>
        <TextBox Grid.Row="0" Grid.Column="1" Width="100" HorizontalAlignment="Center" Text="{Binding PPerson.Fname, Mode=TwoWay}"/>
        <TextBlock Grid.Row="1" Grid.Column="0" Text="Last Name" HorizontalAlignment="Center"/>
        <TextBox Grid.Row="1" Grid.Column="1" Width="100" HorizontalAlignment="Center" Text="{Binding PPerson.LName, Mode=TwoWay}"/>
        <Button Content="Submit" Command="{Binding SubmitCommand}" HorizontalAlignment="Center" Grid.Row="2" Grid.Column="0"/>
        <ListView ItemsSource="{Binding Persons}" Grid.Row="3" Grid.Column="1" Width="Auto">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="First Name" DisplayMemberBinding="{Binding Fname}" Width="Auto"/>
                    <GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding LName}" Width="Auto"/>
                    <GridViewColumn Header="Full Name" DisplayMemberBinding="{Binding FullName}" Width="Auto"/>
                </GridView>
            </ListView.View>            
        </ListView>        
    </Grid>
</Window>


Rich P

解决方案

Well, I got one workaround going -- I added 2 more properties to my Person class which get their values from the original Fname and LName properties.  I call these FFName and LLName and I bind these to the Listview.  Now these properties which are not bound to the 2 textboxes do not get updated. 

I'm not sure if this is a good practice, but I am putting it out there for suggestions on improvements.

Here is my new Person.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Wpf_tmp.Model
{
    public class Person
    {
        private string fName;
        public string Fname 
        {
            get { return fName; }
            set 
            { 
                fName = value; 
            }
        }

        private string lName;
        public string LName 
        {
            get { return lName; }
            set 
            { 
                lName = value; 
            }
        }

        private string fullName;
        public string   FullName
        {
            get
            {
                return fullName = Fname + " " + LName;                
            }
            set
            {
                if (fullName != value)
                {
                    fullName = value;
                }
            }
        }

        private string ffName;
        public string FFName
        {
            get
            {
                return ffName = Fname;
            }
            set
            {
                if (ffName != Fname)
                {
                    ffName = Fname;
                }
            }
        }

        private string llName;
        public string LLName
        {
            get
            {
                return llName = LName;
            }
            set
            {
                if (llName != LName)
                {
                    llName = LName;
                }
            }
        }
    }
}


这篇关于将新数据添加到ObservableCollection并使用MVVM模式绑定到ListView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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