How to make a DXGrid control properly update when DataBound
When the list underlying my databound DXGrid is updated, the scrollbar of the grid updates but the body of the grid does not, at least not right away. As soon as I click on the grid scrollbar, the body does refresh.
To illustrate - here is my application in the initial state:
When I add four new objects to my underlying list, only the scrollbar changes:
Finally, when I press on the "down" button at the bottom of the scrollbar, the entire grid refreshes:
Expected behaviour: The grid should refresh properly whenever the underlying database list is updated, not much 开发者_C百科later when the user tries to interact with the list.
The Xaml for my GridControl looks like this:
<dxg:GridControl dxlc:DockLayoutControl.Dock="Client"
ItemsSource="{Binding Project.TimeSeries}">
<dxg:GridControl.Columns>
... omitted ...
</dxg:GridControl.Columns>
<dxg:GridControl.View>
<dxg:TableView Name="tableView1"
AllowEditing="False"
AllowColumnFiltering="True"
ShowAutoFilterRow="True"
ShowGroupPanel="False"
FocusedRow="{Binding SelectedTimeSeries, Mode=TwoWay}"/>
</dxg:GridControl.View>
</dxg:GridControl>
DataContext
of the form is set to a TimeSeriesPresenter
:
public class TimeSeriesPresenter : ITimeSeriesPresenter
{
public TimeSeriesPresenter(ITimeSeriesVisual view)
: base(view) { ... }
public BuilderProject Project
{ get { ... } set { ... } }
public TimeSeriesDefinition SelectedTimeSeries
{ get { ... } set { ... } }
and a BuilderProject
looks like this:
public class BuilderProject : ViewModelBase
{
public IList<TimeSeriesDefinition> TimeSeries
{ get { ... } }
...
}
Both of these objects implement INotifyPropertyChanged
and the properties are triggering the PropertyChanged
event properly. So, everything should just work, right?
Clearly the DXGrid is receiving some kind of update from the view model, because the scrollbar changes. But why doesn't it repaint entirely?
Is there some kind of "mode" required for a DXGrid to do DataBinding normally? What am I missing?
Update
All of my data objects inherit from ViewModelBase
which implements the INotifyPropertyChanged
interface. In addition to TimeSeriesPresenter
and BuilderProject
(shown above), here's a summary of TimeSeriesDefinition
:
public class TimeSeriesDefinition : ViewModelBase
{
public string SeriesID
{
get { return mSeries; }
set {
if (!Equals(mSeries, value) {
mSeries = value;
OnPropertyChanged("SeriesID");
}
}
}
... etc ...
}
Let me add some additional information. You told that the ViewModel and DataSource implement the INotifyPropertyChanged interface. AM I right in my assumption, that the data object does not implement this interface? If so, I tend to think that this is the cause of this problem.
If the data object class (TimeSeriesDefinition ?) implements this interface, everything should work properly.
Also, a possible cause of this problem is that you are binding to a complex fieldName, i.e.
FieldName="Row.Text"
If this is the case, please let me know, and we will let you know how to resolve the problem.
The source of the problem was this code:
public class BuilderProject : ViewModelBase
{
public IList<TimeSeriesDefinition> TimeSeries
{ get { ... } }
...
}
Even though IList<T>
should be supported, in practice its not.
The requisite fix was to change to using ObservableCollection<T>
instead:
public class BuilderProject : ViewModelBase
{
public ObservableCollection<TimeSeriesDefinition> TimeSeries
{ get { ... } }
...
}
In my case, this led to parallel maintenance of two lists - an underlying IList<>
in the presentation agnostic model, and an ObservableCollection<>
in the ViewModel. Keeping the two lists in sync is a bit of overhead, but not hard to get right.
精彩评论