【问题标题】:ComboBox not updating when ObservableCollection is modified in another View在另一个视图中修改 ObservableCollection 时,组合框不更新
【发布时间】:2017-02-23 17:14:05
【问题描述】:

我正在开发一个用于练习目的的小型 MVVM WPF 项目,我有两个窗口,每个窗口都有一个视图,一个用于显示员工 (MainWindow),一个用于添加员工 (AddPersonWindow)。

在我的 MainWindow 中,有一个绑定到 ObservableCollection 的 ComboBox,我可以通过 MainWindow 中的按钮打开 AddPersonWindow。但是,如果我通过单击保存按钮并执行 AddPerson() 函数从 AddPersonWindow 将员工添加到 ObservableCollection,则 MainWindow 中的 ComboBox 不会更新。如果我从MainWindow 执行相同的AddPerson() 函数,一切都很好,ComboBox 会显示新条目。我在这里错过了什么?

代码:

Person.cs

class Person
{
    public string Surname { get; set; }
    public string Name { get; set; }
    public string Street { get; set; }
    public string HouseNumber { get; set; }
    public string PostalCode { get; set; }
    public string City { get; set; }
    public string PhoneAreaCode { get; set; }
    public string PhoneNumber { get; set; }
    public string Email { get; set; }
    public string FullName { get { return String.Format("{0}, {1}", Name, Surname); } }
}

PersonViewModel.cs

class PersonViewModel : INotifyPropertyChanged
{

    public CommandHandler ButtonClick { get; set; }

    public PersonViewModel()
    {
        CreatePerson();
    }       

    //Combobox SelectedItem
    private Person _selectedPerson;
    public Person SelectedPerson
    {
        get { return _selectedPerson; }

        set
        {
            _selectedPerson = value;
            OnPropertyChanged("SelectedPerson");
        }
    }      



    public ObservableCollection<Person> PersonList { get; set; } = new ObservableCollection<Person>();



    public void CreatePerson()
    {     


        foreach (string line in File.ReadLines(@"C:\some_file.csv", Encoding.GetEncoding("iso-8859-1")))
        {
            string[] substrings = line.Split(',');
            Person person = new Person {
                Surname = substrings[0],
                Name = substrings[1],
                Street = substrings[2],
                HouseNumber = substrings[3],
                PostalCode = substrings[4],
                City = substrings[5],
                PhoneAreaCode = substrings[6],
                PhoneNumber = substrings[7],
                Email = substrings[8] };
                PersonList.Add(person);
        }

    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }


}

AddPersonViewModel.cs

class AddPersonViewModel : PersonViewModel
{


    public AddPersonViewModel()
    {
        ButtonClick = new CommandHandler(AddPerson);
    }

    public string EnteredSurname { get; set; }
    public string EnteredName { get; set; }
    public string EnteredStreet { get; set; }
    public string EnteredHouseNumber { get; set; }
    public string EnteredPostalCode { get; set; }
    public string EnteredCity { get; set; }
    public string EnteredPhoneAreaCode { get; set; }
    public string EnteredPhoneNumber { get; set; }
    public string EnteredEmail { get; set; }



    public void AddPerson()
    {


        Person person = new Person
        {
            Surname = EnteredSurname,
            Name = EnteredName,
            Street = EnteredStreet,
            HouseNumber = EnteredHouseNumber,
            PostalCode = EnteredPostalCode,
            City = EnteredCity,
            PhoneAreaCode = EnteredPhoneAreaCode,
            PhoneNumber = EnteredPhoneNumber,
            Email = EnteredEmail
        };
        PersonList.Add(person);

    }
}

CommandHandler.cs

class CommandHandler : ICommand
{

    Action ExecuteHandler;

    public CommandHandler(Action executeHandler)
    {            
        ExecuteHandler = executeHandler;
    }

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        ExecuteHandler();
    }

}

MainWindow.xaml.cs:

 public MainWindow()
    {
        InitializeComponent();
        DataContext = new PersonViewModel();
    }

AddPersonWindow.xaml.cs:

 public AddPersonWindow()
    {
        InitializeComponent();
        DataContext = new AddPersonViewModel();
    }

MainWindow.xaml 中的组合框:

<ComboBox Width="325" HorizontalAlignment="Left" Margin="7" Grid.Column="1" ItemsSource="{Binding PersonList}" DisplayMemberPath="FullName" SelectedItem="{Binding SelectedPerson}" IsTextSearchEnabled="True" TextSearch.TextPath="FullName" IsEditable="True" />

AddPersonWindow.xaml 中的按钮:

<Button Width="100" Height="30" Margin="15" Grid.Row="3" Grid.Column="2" HorizontalAlignment="Right" IsEnabled="True" Command="{Binding ButtonClick}">Speichern</Button>

【问题讨论】:

  • 他们使用PersonViewModel 的同一个实例吗?假设您正在创建多个PersonViewModel/AddPersonViewModel,因此您有多个PersonList 实例。您应该创建一个AddPersonViewModel 并将实例传递给其他页面/窗口。 (通过构造函数)
  • 我认为你让我走上了正轨。一定是因为我在代码隐藏中创建了一个PersonViewModel 和一个AddPersonViewModel(我在原始帖子中添加了两个代码隐藏文件),因此创建了两个单独的PersonList 实例。虽然我还没有找到解决方法 - 会继续努力!
  • 是的,他们不分享他们的PersonList,所以它不起作用。

标签: c# wpf mvvm combobox observablecollection


【解决方案1】:

我没有设法在两个视图模型之间共享一个 PersonList 实例,所以我决定直接在 AddPersonViewModel 中编辑底层 CSV 文件:

 class AddPersonViewModel
{

    public CommandHandler ButtonClick { get; set; }


    public AddPersonViewModel()
    {
        ButtonClick = new CommandHandler(AddPerson);
    }

    public string EnteredSurname { get; set; }
    public string EnteredName { get; set; }
    public string EnteredStreet { get; set; }
    public string EnteredHouseNumber { get; set; }
    public string EnteredPostalCode { get; set; }
    public string EnteredCity { get; set; }
    public string EnteredPhoneAreaCode { get; set; }
    public string EnteredPhoneNumber { get; set; }
    public string EnteredEmail { get; set; }



    void AddPerson()
    {

        File.AppendAllText(@"C:\some_file.csv", "\r\n" + 
            EnteredSurname + "," +
            EnteredName + "," +
            EnteredStreet + "," +
            EnteredHouseNumber + "," +
            EnteredPostalCode + "," +
            EnteredCity + "," +
            EnteredPhoneAreaCode + "," +
            EnteredPhoneNumber + "," +
            EnteredEmail,
            Encoding.GetEncoding("iso-8859-1")
            );

    }
}
}

为了在另一个视图中添加一个人后刷新PersonViewModel 类视图中的组合框,我实现了一个可以通过单击按钮来执行的方法。为此,我使用以下方法:

public void RefreshPersons()
    {

        PersonList.Clear();
        foreach (string line in File.ReadLines(@"C:\Users\c.philipp\Downloads\adressbuch.csv", Encoding.GetEncoding("iso-8859-1")))
        {
            string[] substrings = line.Split(',');
            Person person = new Person
            {
                Surname = substrings[0],
                Name = substrings[1],
                Street = substrings[2],
                HouseNumber = substrings[3],
                PostalCode = substrings[4],
                City = substrings[5],
                PhoneAreaCode = substrings[6],
                PhoneNumber = substrings[7],
                Email = substrings[8]
            };
            PersonList.Add(person);
        }


    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-16
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2015-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多