[英]Why isn't my property aware of changes made directly to the database
I have a simple View and ViewModel. 我有一个简单的View和ViewModel。 When you click on the ComboBox of Technicians and select a Technician, the Tests for the SelectedTechnician are displayed in the ListView you see below.
当您单击技术员组合框并选择技术员时,针对所选技术员的测试将显示在下面显示的ListView中。 This works perfectly well.
这工作得很好。
Note Technician has a one to many relationship with Test and each is an entity (Code-First Entity Framework). 注意技术人员与Test具有一对多关系,并且每个都是实体(代码优先实体框架)。
MainViewModel.xaml MainViewModel.xaml
<Grid>
<StackPanel>
<ComboBox ItemsSource="{Binding Technicians, Mode=TwoWay}"
DisplayMemberPath="FullName"
SelectedItem="{Binding SelectedTechnician, Mode=TwoWay}">
</ComboBox>
<ListView ItemsSource="{Binding SelectedTechnician.Tests}"
SelectedItem="{Binding SelectedTest}"
HorizontalAlignment="Left" Height="100" Margin="10,10,0,0" VerticalAlignment="Top" Width="271">
<ListView.View>
<GridView>
<GridViewColumn Header="Id" Width="auto" DisplayMemberBinding="{Binding Id}"/>
<GridViewColumn Header="Test" Width="auto" DisplayMemberBinding="{Binding TestTypeName}"/>
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</Grid>
MainWindowViewModel.cs MainWindowViewModel.cs
public class MainWindowViewModel : ViewModelBase
{
private WpfTestBedDb db = new WpfTestBedDb();
public MainWindowViewModel()
{
Technicians = new ObservableCollection<Technician>();
}
private ObservableCollection<Technician> _technicians;
public ObservableCollection<Technician> Technicians
{
get { return _technicians; }
set
{
_technicians = value;
OnPropertyChanged("Technicians");
}
}
private Technician _selectedTechnician;
public Technician SelectedTechnician
{
get { return _selectedTechnician; }
set
{
if (_selectedTechnician != value)
{
_selectedTechnician = value;
OnPropertyChanged("SelectedTechnician");
}
}
}
public void LoadTechnicians()
{
var query = from tech in db.Technicians
select tech;
foreach (var technician in query)
{
Technicians.Add(technician);
}
}
}
Incidentally, to test out the capabilities of DataBinding on the ObservableCollection<Technician> Technicians;
附带地,要测试
ObservableCollection<Technician> Technicians;
上的数据绑定功能ObservableCollection<Technician> Technicians;
, as you see in the ViewModel above, I went into the database through SSMS and added a new Technician WHILE the app was still running. ,如您在上面的ViewModel中所见,我通过SSMS进入数据库并添加了一个新的Technician,而该应用仍在运行。 Once my addition had been made, I went to the app and clicked on my ComboBox of Technicians only to find that the list/UI hadn't been updated.
添加完我的内容后,我转到该应用程序,然后单击我的ComboBox of Technicians,发现列表/ UI尚未更新。 And yet, I would have thought that because I had made the property Technicians an ObservableCollection, and one that raises the
OnPropertyChanged("Technicians");
但是,我会以为,因为我已经将技术人员属性设置为ObservableCollection,并提出了
OnPropertyChanged("Technicians");
, that the UI would have updated. ,则用户界面将已更新。
I did this experiment to simulate two of the same apps running at the same time, each reading and writing to the same database. 我做了这个实验,以模拟同时运行的两个相同应用程序,每个应用程序都读取和写入相同的数据库。
First Question: Why isn't the UI updating despite having my ObservableCollection raise OnPropertyChanged? 第一个问题:尽管我的ObservableCollection提高了OnPropertyChanged,为什么UI没有更新? That is, why isn't it aware of the changes made directly to the database (outside the app)?
也就是说,为什么它不知道直接对数据库(应用程序外部)所做的更改?
Second Question: What do I need to add so that the collection of Technicians is constantly aware of DB changes? 第二个问题:我需要添加什么以便技术人员不断了解数据库更改? (I thought that is what ObservableCollection was for)
(我认为这就是ObservableCollection的目的)
Short version: most data access code is a disconnected model, not a live/connected model. 简短版本:大多数数据访问代码是断开连接的模型,而不是实时/连接的模型。
The "observable" here means "reacts to other changes in that layer", ie other .NET code manipulating the object model. 这里的“可观察的”是指“对该层中的其他更改做出反应”,即操纵对象模型的其他.NET代码。 Using
ObservableCollection<T>
doesn't make a giant hand reach out over the network from the database to tweak the bits. 使用
ObservableCollection<T>
不会使庞大的手从数据库通过网络伸出来调整位。
Making instantly change-aware systems is more complicated than that; 即时创建具有变更意识的系统要比这复杂得多。 frankly I would suggest looking at something like pub/sub if you genuinely need instant updates.
坦率地说,如果您确实需要即时更新,我建议您看一下pub / sub之类的东西。 Otherwise, perhaps consider polling occasionally.
否则, 也许考虑偶尔进行轮询。
Additionally, note that if you do want to do polling, you can't just re-fetch the object via: 此外,请注意,如果您确实想进行轮询,则不能仅通过以下方式重新获取对象:
var stateNow = db.Technicians.Single(x => x.Id == myId);
because that might just hand you back the same object you already have ; 因为这样可能会使您退回已经拥有的同一对象 ; a lot of ORMs have an identity cache built in. To actually re-fetch the object you will need a second db-context instance.
许多ORM都内置有身份缓存。要真正重新获取对象,您将需要第二个db-context实例。
In addition to Marc Gravell's answer, and in answer to your second question, you might like to check out the SqlDependency
class. 除了Marc Gravell的答案以及第二个问题的答案外,您可能想查看
SqlDependency
类。
Quoting from the documentation : 引用文档 :
The SqlDependency object represents a query notification dependency between an application and an instance of SQL Server.
SqlDependency对象表示应用程序和SQL Server实例之间的查询通知依赖关系。 An application can create a SqlDependency object and register to receive notifications via the OnChangeEventHandler event handler.
应用程序可以创建SqlDependency对象并注册以通过OnChangeEventHandler事件处理程序接收通知。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.