When edit first name and last name, full name can change correspondingly.
But once it is added to a collection, and point to a new Player, textbox won't update and lost binding.
Does any one know how to solve this? any better way to add new object to collection?

Code:
<Window x:Class="MonitoredUndo_Test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Width="525"
        Height="350" Loaded="Window_Loaded" >
    <UniformGrid>
        <Button Width="40"
                Height="20"
                Click="Button_Click"
                Content="undo" />
        <Button Width="40"
                Height="20"
                Click="Button_Click_1"
                Content="+" />
        <TextBox x:Name="tb1"
                 Width="100"
                 Height="25"
                 Text="{Binding Path=Player.FirstName,
                                UpdateSourceTrigger=PropertyChanged,
                                RelativeSource={RelativeSource FindAncestor,
                                                               AncestorType={x:Type Window}}}" />
        <TextBox x:Name="tb2"
                 Width="100"
                 Height="25"
                 Text="{Binding Path=Player.LastName,
                                UpdateSourceTrigger=PropertyChanged,
                                RelativeSource={RelativeSource FindAncestor,
                                                               AncestorType={x:Type Window}}}" />
        <TextBox x:Name="tb3"
                 Width="100"
                 Height="25"
                 Text="{Binding Path=Player.FullName,
                                UpdateSourceTrigger=PropertyChanged,
                                Mode=OneWay,
                                RelativeSource={RelativeSource FindAncestor,
                                                               AncestorType={x:Type Window}}}" />
        <ListBox Width="200"
                 Height="200"
                 ItemsSource="{Binding Path=Players.FullName,
                                       RelativeSource={RelativeSource FindAncestor,
                                                                      AncestorType={x:Type Window}}}" />

    </UniformGrid>
</Window>
Code:
namespace MonitoredUndo_Test {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window {
        public ObservableCollection<Player> Players { get; set; }
        public  Player Player { get; set; }
        public MainWindow() {
            InitializeComponent();
            Players = new ObservableCollection<Player>();
            Player = new Player() { FirstName = "John" };
        }

        private void Button_Click(object sender, RoutedEventArgs e) {
            var undoRoot = UndoService.Current[this];
            undoRoot.Undo();
        }

        private void Button_Click_1(object sender, RoutedEventArgs e) {
            //Players.Add(Player);
            Player = new Player() {FirstName="Test" ,LastName="1" };
            //Player.FirstName = "1";
            //Player.LastName = "2";
        }

        private void Window_Loaded(object sender, RoutedEventArgs e) {
            Player = new Player() { FirstName = "John1" };
        }

    }
}
Code:
namespace MonitoredUndo_Test {
    public class Player : ISupportsUndo, INotifyPropertyChanged {
        private string _FirstName;
        public string FirstName {
            get { return _FirstName; }
            set {
                if (value == _FirstName)
                    return;

                DefaultChangeFactory.OnChanging(this, "FirstName", _FirstName, value, "First Name Changed");

                _FirstName = value;
                OnPropertyChanged("FirstName"); // Tells the UI that this property has changed.
                OnPropertyChanged("FullName");  // If FirstName changes, then FullName is also affected.
            }
        }

        private string _LastName;
        public string LastName {
            get { return _LastName; }
            set {
                if (value == _LastName)
                    return;
                DefaultChangeFactory.OnChanging(this, "LastName", _LastName, value, "Last Name Changed");

                _LastName = value;
                OnPropertyChanged("LastName");  // Tells the UI that this property changed.
                OnPropertyChanged("FullName");  // If LastName changes, then FullName is also affected.
            }
        }
        public string FullName {
            get {
                return string.Format("{0} {1}", FirstName, LastName);
            }
        }
        #region ISupportsUndo Members


        public object GetUndoRoot() {
            return this;
        }

        #endregion
        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;


        protected void OnPropertyChanged(string propertyName) {
            // Validate the property name in debug builds
            //VerifyProperty(propertyName);

            if (null != PropertyChanged) {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }


        #endregion
    }
}