问题描述
我在使用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"的HorizontalAlignment = QUOT;中心" />
< TextBox Grid.Row =" 0" Grid.Column = QUOT 1 QUOT;宽度= QUOT; 100"的HorizontalAlignment = QUOT;中心" Text =" {Binding PPerson.Fname,Mode = TwoWay}" />
< TextBlock Grid.Row =" 1" Grid.Column = QUOT; 0" Text =" Last Name"的HorizontalAlignment = QUOT;中心" />
< TextBox Grid.Row =" 1" Grid.Column = QUOT 1 QUOT;宽度= QUOT; 100"的HorizontalAlignment = QUOT;中心" Text =" {Binding PPerson.LName,Mode = TwoWay}" />
< Button Content ="提交" Command =" {Binding SubmitCommand}"的HorizontalAlignment = 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
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
这篇关于将新数据添加到ObservableCollection并使用MVVM模式绑定到ListView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!