Reputation: 23
I'm somewhat a novice to WPF apps, but this seems to be such a simple thing going wrong that I am stumped. I've tried to search for an answer, but most of what I find are Binding errors which isn't the case here.
Essentially, I have a WPF app accessing a database to display items to the user. Said data is held in a grid on the view, the visibility of which is determined by a boolean property (RecordLoaded) that implements OnPropertyChanged and the standard BoolToVisibility converter.
DataView.xaml:
<Grid Visibility="{Binding RecordLoaded, Converter={StaticResource BoolToVisibility}}">
When an item on a treeview is selected, a SelectedRecord class is updated, which then in turn fires an event (OnRecordSelected) to set RecordLoaded to false and call a function (FillDetails) to grab the relevant data.
private void DataSelectedRecord_OnRecordSelected(object sender, EventArgs e)
{
RecordLoaded = false;
FillDetails();
}
After all data has been grabbed from the database, at the end of FillDetails, RecordLoaded is set to true.
The trouble is, I'm trying to implement a bit of 'flicker' to signify the view has updated by way of turning the visibility of the grid on and off, especially when dealing with data that has minimal differences between two records. But while I can move the grid from an initial Visibility.Hidden state to Visible by using the converter, and the converter works correctly throughout, returning the correct Hidden or Visible as and when the boolean is set to false and true, there is absolutely no change from the visual side of things, not even a flicker.
My first thought was that the states were changing back to true that quickly that it was undetectable, but I added a delay into the FillDetails method just before the boolean with no joy.
Does anyone have any suggestions as to what could be going wrong, or perhaps even alternate ways of signifying the data has updated (without an obtrusive message or otherwise)?
Upvotes: 0
Views: 68
Reputation: 128098
Everything happens synchronously in the UI thread, so the UI hasn't got a chance to update. You may declare the event handler async, run FillDetails in a Task and await it:
private async void DataSelectedRecord_OnRecordSelected(object sender, EventArgs e)
{
RecordLoaded = false;
await Task.Run(() => FillDetails());
RecordLoaded = true;
}
Note however that when FillDetails accesses UI elements or data the UI elements are bound to, it might be necessary do that inside a Dispatcher.Invoke
or BeginInvoke
call.
If the database API allows async access, you may perhaps also declare FillDetails async and await asynchronous API calls. Then you wouldn't need Task.Run:
private async void DataSelectedRecord_OnRecordSelected(object sender, EventArgs e)
{
RecordLoaded = false;
await FillDetails();
RecordLoaded = true;
}
private async Task FillDetails()
{
var queryResults = await someDbApiCallAsync();
// do something with it
}
Upvotes: 2