且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

将新数据添加到ObservableCollection并使用MVVM模式绑定到ListView

更新时间:2022-10-21 09:01:47

好吧,我有一个解决方法 - 我在Person类中添加了另外两个属性,它们从原始的Fname和LName属性中获取它们的值。&nbsp ;我调用这些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;
                }
            }
        }
    }
}