我有一个简单的View和ViewModel。当您单击ComboBox of Technicians并选择技术人员时,SelectedTechnician的测试将显示在您看到的ListView中。这非常有效。
注意技术人员与Test有一对多的关系,每个人都是一个实体(代码优先实体框架)。
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
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);
}
}
}
顺便说一句,要在ObservableCollection<Technician> Technicians;
上测试DataBinding的功能,正如您在上面的ViewModel中看到的那样,我通过SSMS进入了数据库,并在应用程序仍在运行时添加了一名新的技术人员。添加完成后,我转到应用程序并单击我的ComboBox of Technicians,发现列表/ UI尚未更新。然而,我会想到,因为我已经使属性技术人员成为ObservableCollection,并且提升了OnPropertyChanged("Technicians");
,UI将更新。
我做了这个实验来模拟同时运行的两个相同的应用程序,每个应用程序都读取和写入同一个数据库。
第一个问题:尽管我的ObservableCollection引用了OnPropertyChanged,为什么UI不更新?也就是说,为什么它不知道直接对数据库进行的更改(在应用程序之外)?
第二个问题:我需要添加什么才能让技术人员的集合始终了解数据库更改? (我认为这就是ObservableCollection的用途)
答案 0 :(得分:3)
简短版本:大多数数据访问代码是已断开连接的模型,而非实时/已连接模型。
这里的“可观察”意味着“对该层中的其他变化做出反应”,即操纵对象模型的其他.NET代码。使用ObservableCollection<T>
不会让巨手从数据库通过网络伸出来调整位数。
即时更改感知系统比这更复杂;坦率地说,如果你真的需要即时更新,我会建议看看像pub / sub这样的东西。否则,或许偶尔会考虑轮询。
此外,请注意,如果执行想要进行轮询,则不能仅通过以下方式重新获取对象:
var stateNow = db.Technicians.Single(x => x.Id == myId);
因为可能只是将你已经拥有的同一对象交给你了;很多ORM都内置了身份缓存。要实际重新获取对象,您需要第二个db-context实例。
答案 1 :(得分:2)
除了Marc Gravell的回答,并回答第二个问题,您可以查看SqlDependency
课程。
SqlDependency对象表示应用程序与SQL Server实例之间的查询通知依赖关系。应用程序可以创建SqlDependency对象并注册以通过OnChangeEventHandler事件处理程序接收通知。