失去焦点时列表框中的文本框不更新

Textbox in listbox not updating when lostfocus

我在列表框中有一个文本框,我想在文本框失去焦点时更新 ObservableCollection。我尝试使用 post here 中描述的集合 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 中某个项目的 adding/removing 逻辑。没有必要监视 属性 changed 事件,因为每个对象都会在其中的 属性 发生变化时引发事件。

这是我的:

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>