ObservableCollection不更新=> DataGrid UI不会显示所有内容

时间:2019-06-07 09:01:15

标签: c# dapper

我写的某些代码有问题。 我正在尝试建立一个申请人管理程序。 我有一个SQL Server,这是我的数据库。

在程序开始时,将DataGrid绑定到ObservableCollection 通过Dapper触发SQL SELECT。

如果我通过另一个SQL查询插入新的申请人,则DataGrid不会显示此新的申请人。

我调试了程序,看看出了什么问题。 我认为这是我绑定的ObservableCollection。

DataGrid代码

<DataGrid x:Name="DgInformation" ItemsSource="{Binding AllData,Mode=TwoWay}"
                  SelectedItem="{Binding SelectedApplicantModel, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
                  AutoGenerateColumns="False"
                  Grid.Row="2"
                  MaxHeight="870"
                  IsSynchronizedWithCurrentItem="True"
                  IsReadOnly="True"
                  CanUserAddRows="False"
                  CanUserDeleteRows="False"
                  HorizontalAlignment="Center"
                  Margin="10,5,10,5"
                  Background="#F5F5F5"
                  AlternatingRowBackground="#eeeeee" AlternationCount="2">
            <DataGrid.RowStyle>
                <Style TargetType="{x:Type DataGridRow}">
                    <EventSetter Event="MouseDoubleClick" Handler="DG_Information_MouseDoubleClick" />
                    <EventSetter Event="KeyDown" Handler="DG_Information_KeyDown" />
                </Style>
            </DataGrid.RowStyle>
            <DataGrid.Columns>
                <materialDesign:MaterialDataGridTextColumn Header="Vorname" Width="110"
                                                           EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"
                                                           Binding="{Binding FirstName,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                <materialDesign:MaterialDataGridTextColumn Header="Nachname" Width="110"
                                                           EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"
                                                           Binding="{Binding LastName,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                <materialDesign:MaterialDataGridTextColumn Header="Geburtstag" Width="110"
                                                           EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"
                                                           Binding="{Binding Birthday,Mode=TwoWay, StringFormat=\{0:dd.MM.yy\}, UpdateSourceTrigger=PropertyChanged}" />
                <materialDesign:MaterialDataGridTextColumn Header="Schulabschluss" Width="140"
                                                           EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"
                                                           Binding="{Binding Graduation.Graduation,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                <materialDesign:MaterialDataGridTextColumn Header="PLZ" Width="90"
                                                           EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"
                                                           Binding="{Binding PostCode,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                <materialDesign:MaterialDataGridTextColumn Header="Ort"
                                                           EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"
                                                           Binding="{Binding Address.HomePlace, Mode =TwoWay,UpdateSourceTrigger=PropertyChanged}" />
                <materialDesign:MaterialDataGridTextColumn Header="Geschlecht"
                                                           EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"
                                                           Binding="{Binding Gender.Gender,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                <DataGridHyperlinkColumn Header="E-Mail"
                                         EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"
                                         Binding="{Binding EMail, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
                    <DataGridHyperlinkColumn.ElementStyle>
                        <Style>
                            <EventSetter Event="Hyperlink.Click" Handler="DgHyperlinkClick" />
                        </Style>
                    </DataGridHyperlinkColumn.ElementStyle>
                </DataGridHyperlinkColumn>
                <materialDesign:MaterialDataGridTextColumn Header="Stelle"
                                                           EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"
                                                           Binding="{Binding Job,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                <materialDesign:MaterialDataGridTextColumn Header="Bewertung"
                                                           EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"
                                                           Binding="{Binding Grade.Grade, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
            </DataGrid.Columns>
        </DataGrid>

我的ViewModel

public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private ObservableCollection<ApplicantModel> _allData;

        public BaseViewModel()
        {
            AllData = ApplicantService.GetInstance().GetAll();
        }

        public ObservableCollection<ApplicantModel> AllData
        {
            get { return _allData; }
            set
            {
                _allData = value;
                OnPropertyChanged();
            }
        }

我的服务等级

private readonly IApplicantRepository _repository;

        public ApplicantService()
        {
            _repository = new ApplicantRepository();
        }

        public ObservableCollection<ApplicantModel> GetAll()
        {
            return _repository.GetAll();
        }

我的存储库

public ObservableCollection<ApplicantModel> GetAll()
        {
                var result =
                    Db.Query<ApplicantModel, AddressModel, GraduationModel, GenderModel, GradeModel, ApplicantModel>(
                        "SELECT a.ID, a.FirstName, a.LastName, a.Birthday, a.EMail, a.Job, ad.PostCode, ad.HomePlace, g.Graduation, g.ID, ge.Gender, ge.ID, Grade.Grade FROM dbo.Applicant As a INNER JOIN Address As ad ON ad.PostCode = a.PostCode INNER JOIN Graduation As g ON g.ID = a.GraduationID INNER JOIN Gender As ge On ge.ID = a.GenderID INNER JOIN Grade ON Grade.Grade = a.GradeID",
                        _mapSelectGetAll, splitOn: "HomePlace,Graduation,Gender,Grade");
                Logger.LogInfo("Function GetAll executed in ApplicantRepository!");

                ObservableCollection<ApplicantModel> obsCollection = new ObservableCollection<ApplicantModel>(result);
                return obsCollection;
        }

        private ApplicantModel _mapSelectGetAll(ApplicantModel applicant, AddressModel address, GraduationModel graduation, GenderModel gender, GradeModel grade)
        {
            applicant.Graduation = graduation;
            applicant.Address = address;
            applicant.Gender = gender;
            applicant.Grade = grade;

            return applicant;
        }

我希望任何人都能告诉我错误在哪里。

2 个答案:

答案 0 :(得分:0)

您的分析就来了:)与AllData的绑定确实存在问题,主要是因为您允许将其重新分配给设置器。

您的DataGrid实际上只是在监听ObservableCollection的更改(或更确切地说,是在处理INotifyCollectionChanged接口。它不知道您的父对象已经更改了集合本身。 (即使您触发了PropertyChanged事件)

理想情况下,您应该自动初始化可观察的集合,并且不允许对其进行任何外部设置。让它通过CollectionChanged处理添加/删除/重置。

好处是,您现在可以以更简单的方式编写程序(无需传递ObservableCollection<T>

因此,您的viewmodel属性将转到:

public IList<ApplicantModel> AllData { get; } = new ObservableCollection<ApplicationModel>();

因为ObservableCollection<T>是从IList<T>继承而来,所以将其简化是没有问题的。 DataGrid仍会检测到INotifyCollectionChanged界面。

但这确实意味着您不能再为该属性分配新的集合,但这本质上是一件好事:)此外,AllData属性永远不会为null,这是另一件好事。

但是,您现在需要重写在AllData上更新ViewModel属性的逻辑

因此,如果您仍然想在构造函数中自动填充它,可以将viewmodel属性和构造函数更改为:

public BaseViewModel() {
    AllData = new ObservableCollection<ApplicantModel>( ApplicantService.GetInstance().GetAll() );
} 

public IList<ApplicantModel> AllData { get; }

并且不需要私有后备字段,您现在有了一个只读自动属性,并且构造函数将ObservableCollection<T>的{​​{3}}用作了

然后,您应该更改服务类,实际上没有任何理由让它返回完整的ObservableCollection<ApplicantModel>(),只需让它返回IEnumerable<ApplicantModel>或最多返回IReadOnlyList<ApplicantModel>。< / p>

然后,此更改还需要转到您的Repository

然后最终使您可以处理数据的删除和更新。如果您正在使用某些本地数据库,那么只需执行保存/删除请求就可以了,如果您使用的是中央数据库,则可能会涉及很多问题:)

希望不是很多文字:)

答案 1 :(得分:0)

@冰激凌

我的插入查询是:

public void CreateApplicant(ApplicantModel applicant, AddressModel address, GraduationModel graduation, GenderModel gender, GradeModel grade)
        {
            string query = "INSERT INTO Applicant(FirstName,LastName,PostCode,Birthday,GenderID,Email,Job,GraduationID,GradeID)" + "Values(@FirstName,@LastName,@PostCode,@Birthday,@Gender,@Email,@Job,@Graduation,@Grade)";

            try
            {
                Db.Execute(query, new
                {
                    FirstName = applicant.FirstName,
                    LastName = applicant.LastName,
                    Birthday = applicant.Birthday,
                    PostCode = applicant.PostCode,
                    Graduation = graduation.ID,
                    Gender = gender.ID,
                    Email = applicant.EMail,
                    Job = applicant.Job,
                    Grade = grade.Grade,
                });
                Logger.LogInfo("Function AddApplicant executed in ApplicantRepository!");
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

然后将不同的详细信息填充到绑定到数据库属性的文本框中