我有一个列表框里面的文本框,我想在文本框失去焦点时更新ObservableCollection。我尝试使用这篇文章中描述的我的collections CollectionChanged事件来解决这个问题。现在更新集合的唯一方法是从列表框中添加或删除一个项目。我是不是走错路了?文本框更新集合时遗漏了什么?
MainWindow.xaml
<ListBox ItemsSource="{Binding DataLogList,Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding DataLogLabel}" Margin="5"/>
<TextBox Text="{Binding DataLogName,Mode=TwoWay,UpdateSourceTrigger=LostFocus}" Margin="5" Width="150"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
MainViewModel.cs
public MainViewModel()
{
DataLogList = new ObservableCollection<DataLogContent>();
DataLogList.CollectionChanged += (s, e) =>
{
if (e.NewItems != null)
{
foreach (DataLogContent item in e.NewItems)
{
item.PropertyChanged += item_PropertyChanged;
}
}
if (e.OldItems != null)
{
foreach (DataLogContent item in e.OldItems)
{
item.PropertyChanged -= item_PropertyChanged;
}
}
};
}
void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
NotifyPropertyChanged();
}
DataLogContent.cs
public class DataLogContent:ViewModelBase
{
private string dataLogLabel;
public string DataLogLabel
{
get { return this.dataLogLabel; }
set
{
this.dataLogLabel = value;
NotifyPropertyChanged();
}
}
private string dataLogName;
public string DataLogName
{
get { return this.dataLogName; }
set
{
this.dataLogLabel = value;
NotifyPropertyChanged();
}
}
}
我让它基于此工作。我的猜测是,您可能过度复杂化了ObservableCollection
中项目的添加/删除逻辑。不需要监视属性更改事件,因为每个对象都会在其内部的属性更改时引发事件。
我有:
namespace WpfApplication1
{
public class MainViewModel : ViewModelBase
{
public ObservableCollection<DataLogContent> DataLogList { get; private set; }
public MainViewModel()
{
DataLogList = new ObservableCollection<DataLogContent>();
DataLogList.Add(new DataLogContent
{
DataLogLabel = "Label",
DataLogName = "Name"
});
DataLogList.Add(new DataLogContent
{
DataLogLabel = "Label2",
DataLogName = "Name2"
});
}
}
public class DataLogContent : ViewModelBase
{
private string dataLogLabel;
public string DataLogLabel
{
get { return this.dataLogLabel; }
set
{
this.dataLogLabel = value;
OnPropertyChanged("DataLogLabel");
}
}
private string dataLogName;
public string DataLogName
{
get { return this.dataLogName; }
set
{
this.dataLogName = value;
OnPropertyChanged("DataLogName");
}
}
}
}
简单ViewModelBase: namespace WpfApplication1
{
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string property)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(property));
}
}
}
}
Xaml: <Window x:Class="WpfApplication1.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">
<ListBox ItemsSource="{Binding DataLogList,Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding DataLogLabel}" Margin="5"/>
<TextBox Text="{Binding DataLogName,Mode=TwoWay,UpdateSourceTrigger=LostFocus}" Margin="5" Width="150"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Window>