我写的某些代码有问题。 我正在尝试建立一个申请人管理程序。 我有一个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;
}
我希望任何人都能告诉我错误在哪里。
答案 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);
}
}
然后将不同的详细信息填充到绑定到数据库属性的文本框中