Reputation: 97
I have a dataset with an unknown number of columns that I am populating into a DataGrid
. I would like to be able to asynchronously format cell contents using different formatters. For example, a complex object that might take some time-bound processing. Note these requirements exclude use of IConverter
.
I have defined a class AsyncFormatter
that wraps INotifyTask
(see this link).
public class AsyncFormatter
{
public NotifyTask<string?> FormattedResult { get; private set; }
public AsyncFormatter()
{
}
public void Start()
{
var t = new Task<string?>(() => ExecuteAsync().Result);
FormattedResult = NotifyTask.Create(t);
t.Start();
}
private async Task<string?> ExecuteAsync()
{
return await DoAsyncFormattingWork();
}
}
In the DataGrid
's AutoGeneratingColumn
callback, I am binding a given cell to the asynchronous result of a given formatter. I have seen a few approaches in somewhat related SO questions on how to bind the async formatter, but using ElementStyle
and TextBlock
seem to be most promising:
private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
var textColumn = e.Column as DataGridTextColumn;
var asyncFormatter = new AsyncFormatter();
textColumn.ElementStyle = new Style(typeof(TextBlock));
textColumn.ElementStyle.Setters.Add(new Setter(TextBlock.TagProperty, asyncFormatter));
textColumn.ElementStyle.Setters.Add(new Setter(TextBlock.TextProperty, new Binding
{
Source = asyncFormatter,
Path = new PropertyPath("FormattedResult.Result"),
FallbackValue = "<Please wait...>",
IsAsync = true,
}));
textColumn.ElementStyle.Setters.Add(new EventSetter(
TextBlock.LoadedEvent, new RoutedEventHandler((s, args) =>
{
var textBlock = s as TextBlock;
var asyncFormatter = textBlock.Tag as AsyncFormatter;
if (asyncFormatter == null)
{
Debug.Assert(false);
return;
}
var contents = textBlock.Text;
asyncFormatter.Start(evt, contents, colName);
})));
What is not working in the above approach is the binding of TextBlock.TextProperty
. It appears to be completely blown away by whatever is setting the TextBlock
's initial Text
value. So while the async formatter runs, the value is never propagated back to the TextBlock
.
Is there a better approach?
Upvotes: 0
Views: 37