I have a DataGrid (in a prowindow) whose itemsource is bound to a DataTable. When the user clicks a button, I want the DataGrid to update with values as stipulated by the binding on the button. I have confirmed that when the button is clicked, the DataTable values are updated but the DataGrid doesn't update the user interface with the updated values.
This is the xaml for the datagrid:
!<DataGrid Grid.Row="1" Margin="5" Name="selectedFeatureGrid"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
Style="{DynamicResource Esri_DataGrid}"
AutoGenerateColumns="True"
HorizontalAlignment="Stretch"
HeadersVisibility="Column"
RowHeaderWidth="0"
IsReadOnly="True"
SelectionMode="Single"
SelectedItem="{Binding Path=SelectedIntersectionRow}"
ItemsSource="{Binding Path=IntersectionDataTable, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
AutoGeneratingColumn="selectedFeatureGrid_AutoGeneratingColumn">
</DataGrid>
Solved! Go to Solution.
Hi Marvis Kisakye,
For DataTable, your case is autogenerate column case.
So at your viewmodel for datasource property you need to declare like this.
private DataTable _intersectionDataTable;
public DataView IntersectionDataTable
{
get
{
return this._intersectionDataTable.DefaultView;
}
}
Next step, Make sure _intersectionDataTable datatable is initialized first. (Not necessary to create all columns). Just like this._intersectionDataTable = new DataTable() is good enough.
In your button click event.
Make sure manipulations are going through with _intersectionDataTable property.
After all DataColumns generation and DataRows added statement finished, just call this statement. this.NotifyPropertyChanged("IntersectionDataTable");
Currently this way of solution is working for me, let me know if you encounter issue. Or just share your sample xaml and viewmodel.
Hi Marvis Kisakye,
For DataTable, your case is autogenerate column case.
So at your viewmodel for datasource property you need to declare like this.
private DataTable _intersectionDataTable;
public DataView IntersectionDataTable
{
get
{
return this._intersectionDataTable.DefaultView;
}
}
Next step, Make sure _intersectionDataTable datatable is initialized first. (Not necessary to create all columns). Just like this._intersectionDataTable = new DataTable() is good enough.
In your button click event.
Make sure manipulations are going through with _intersectionDataTable property.
After all DataColumns generation and DataRows added statement finished, just call this statement. this.NotifyPropertyChanged("IntersectionDataTable");
Currently this way of solution is working for me, let me know if you encounter issue. Or just share your sample xaml and viewmodel.
This works beautifully. Thanks! By the way, what setting do you use to get your code snippet to be formatted? I tested all the available options to no avail.
I have problems with this feature too. It doesn't work for me when I reply through the Notification list in my geonet inbox (this might be fixed by now ... I haven't tried it in years), but I get it to work once I navigate to the geonet question link (by clicking on the geonet question). From the geonet question link, you click "Reply" and then you click on the "..." menu in you reply edit menu bar,
that opens up more options. Next you click the "More" pull-down and choose syntax highlighter.
In the syntax highlighter popup choose the format from the pull down and paste the text. The text will be highlighted to make code and xml more readable. you can also use Ctrl+V to paste an image from your clipboard.
There are multiple examples in the Pro SDK community samples repo that are displaying a DataTable in a DataGrid control. You can use the GitHub search, on the top left on the Pro SDK community samples repo page, to search for the term "DataTable" to find all samples. For example: Map-Exploration IdentifyWindow is using a DataTable to autogenerate columns and display a table. As Than mentioned in the reply above you need to call either NotifyPropertyChanged("...") or you can also define your DataTable property with a setter that calls SetProperty(...).
Both NotifyPropertyChanged and SetProperty notify the UI that the DataTable property changed causing the UI to update its content. So your ViewModel property would look like this:
private DataTable _intersectionDataTable = new DataTable();
public DataTable IntersectionDataTable
{
get { return _intersectionDataTable; }
set
{
SetProperty(ref _intersectionDataTable, value, () => IntersectionDataTable);
}
}
You XAML should look like this:
<DataGrid Grid.Row="1" Margin="5" Name="selectedFeatureGrid"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
Style="{DynamicResource Esri_DataGrid}"
AutoGenerateColumns="True"
HorizontalAlignment="Stretch"
HeadersVisibility="Column"
RowHeaderWidth="0"
IsReadOnly="True"
SelectionMode="Single"
SelectedItem="{Binding Path=SelectedIntersectionRow}"
ItemsSource="{Binding Path=IntersectionDataTable, Mode=OneWay}" >
</DataGrid>
And to update / change the DataTable in your code you would have to first define the new DataTable and then call the DataTable's ItemSource property's setter:
// note: all columns are string types, listColumnNames contains the name for each column
// and listValues contains a list of strings for each row
var newDataTable = new DataTable();
foreach (var col in listColumnNames) {
newDataTable.Columns.Add(new DataColumn(col.Key, typeof(string)) { Caption = col.Value });
}
foreach (var row in listValues) {
var newRow = newDataTable.NewRow();
newRow.ItemArray = row.ToArray();
newDataTable.Rows.Add(newRow);
}
// set the new property and notify the UI
// this Update has to be made from the UI thread
IntersectionDataTable = newDataTable;
Make sure that you call the IntersectionDataTable setter from the UI thread (Note that this is true for all properties that are databound to WPF controls).
I didn't realize that SetProperty notifies the UI. Good to know. Thanks!