WPF DataGrid在代码中更新其ItemsSource时不更新UI

时间:2018-01-19 15:26:52

标签: wpf mvvm datagrid

如果在代码中更改了ObservableCollection的项目,我应该怎么做才能使WPF DataGrid显示更改?

<DataGrid HorizontalAlignment="Left" Height="100" Margin="54,25,0,0" VerticalAlignment="Top" Width="264" 
    IsSynchronizedWithCurrentItem="True" AutoGenerateColumns="False" 
    ItemsSource="{Binding DataSource}" SelectedItem="{Binding SelectedPerson}">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding FirstName}" />
        <DataGridTextColumn Binding="{Binding LastName}" />
    </DataGrid.Columns>
</DataGrid>

我在代码中更新SelectedPerson.FirstName并执行DataSource的setter。当前DataSource.FirstName已更新,但DataGrid不显示更改。如果单击列标题,DataGrid将刷新并显示已更改的数据。当我使用MVVM并且没有对DataGrid的引用时,如何使其快速刷新?

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class VM : Notifier
{
    private ObservableCollection<Person> dataSource;
    public ObservableCollection<Person> DataSource
    {
        get { return dataSource; }
        set
        {
            dataSource = value;
            OnPropertyChanged("DataSource");
        }
    }

    private Person selectedPerson;
    public Person SelectedPerson
    {
        get { return selectedPerson; }
        set
        {
            selectedPerson = value;
            OnPropertyChanged("SelectedPerson");
        }
    }

    private string string1;
    public string String1
    {
        get { return string1; }
        set
        {
            string1 = value;
            OnPropertyChanged(String1);
        }
    }

    public VM()
    {
        String1 = "abc";

        DataSource = new ObservableCollection<Person>();
        DataSource.Add(new Person { FirstName = "Alpha", LastName = "Apple" });
        DataSource.Add(new Person { FirstName = "Beta", LastName = "Banana" });
        DataSource.Add(new Person { FirstName = "Charlie", LastName = "Cucumber" });
    }

    public ICommand SetSelectedCommand => new RelayCommandBase(SetSelected);
    private void SetSelected(object parameter = null)
    {
        SelectedPerson.FirstName = String1;
        SelectedPerson = SelectedPerson;    // force setter to run
        DataSource = DataSource;            // force ObservableCollection setter to run
    }
}

2 个答案:

答案 0 :(得分:1)

Person类应该实现INotifyPropertyChanged接口:

public class Person : INotifyPropertyChanged
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            _firstName = value;
            NotifyPropertyChanged();
        }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            _lastName = value;
            NotifyPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

答案 1 :(得分:0)

您的更改未反映为正在更新的项目(人员)不会提出更改通知以更新UI。为此,您需要更新Person类以在Person类中实现接口INotifyPropertyChanged,这与您在viewmodel中实现的方式相同,这应该可行。

public class Person:Notifier
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            _firstName = value;
            OnPropertyChanged(nameof(this.FirstName));
        }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            _lastName = value;
            OnPropertyChanged(nameof(this.LastName));
        }
    }
}

还有一件事。在您的.NET Framework版本中如果支持,您可以使用C# nameof 以字符串形式获取属性名称,而不是对名称进行硬编码。当您重构/重命名属性时,这会有所帮助。