Let's say I have a WPF control that was bound to some DataContext. Now let's say I have some UI code that needs to get some value from the DataContext. How do I do that?
I am aware of the following workarounds:
Cast the DataContext to its original type, e.g.
var myValue = ((MyViewModel)myControl.DataContext).SomeProperty;
or
var myValue = ((DataRowView)myControl.DataContext).Item("SomeDatabaseField");
I don't like this, because it means that in my UI code I need information about the type of the underlying data source.
Bind the required value to some UI field and extract it from there, e.g.
<Button Click="..." Tag="{Binding SomeProperty}" />
and in code
var myValue = (TypeOfMyValue)myButton.Tag;
Is there some generic way to extract a value from a DataContext, i.e., do whatever Binding
does to get the value? I'm looking for something like this:
var myValue = SomeGenericExtractMethod(myControl.DataContext, "SomeProperty");
I'm pretty sure that something like this exists (after all, Binding
works like this), I just cannot find it...
I found a way which works for both ViewModel classes (CLR properties) and lists bound to a ADO.NET DataTables (DataRowView fields), which is to use the TypeDescriptor offered by both:
var myValue = TypeDescriptor.GetProperties(myControl.DataContext)["SomeProperty"]
.GetValue(myControl.DataContext);
Here is a short working example:
var vm = new { MyString = "Test1" }; // ViewModel
var dt = new DataTable();
dt.Columns.Add("MyString", typeof(String));
dt.Rows.Add("Test2");
var drv = dt.DefaultView[0]; // DataRowView
var value1 = TypeDescriptor.GetProperties(vm)["MyString"].GetValue(vm);
var value2 = TypeDescriptor.GetProperties(drv)["MyString"].GetValue(drv);
// value1 = "Test1", value2 = "Test2"