You don't have to use reflection. Alternatives would include using some kind of external metadata to match up UI and data (and possibly generating code and UI from that metadata) or trying to statically analyse your code (perhaps using Roslyn!) to generate a suitable UI. However, reflection is likely to be far less painful. Potential downsides...
- If you have deeply nested or complicated data structures you want to expose in the UI, it can be quite difficult to decide how best to do this.
- If you don't have a clear set of 'UI-facing' objects with consistent rules for visibility, you'll have to spent time creating some kind of attribute or convention-based scheme to ensure you only expose the things you want to expose.
- You may only find out at runtime (worst-case, in deployment) that you fail to correctly expose some rarely-used type.
Having said all that, if your data-types are generally just bags of properties, reflection is very straightforward. Here's some toy code that shows most of the relevant tricks you'll need, including setting up data-binding. Note that it is conventional to use properties rather than bare fields when reflecting over objects.
class Program
{
[STAThread]
static void Main(string[] args)
{
var request = new TripRequest() {Airline = "Reflection Airways"};
var window = new Window();
var stackPanel = new StackPanel();
window.Content = stackPanel;
foreach (var property in request.GetType().GetProperties())
{
Console.WriteLine("Property named {0} has type {1}", property.Name, property.PropertyType);
if (property.PropertyType == typeof(string))
{
var textBox = new TextBox();
var binding = new Binding();
binding.Source = request;
binding.Path = new PropertyPath(property.Name);
BindingOperations.SetBinding(textBox, TextBox.TextProperty, binding);
stackPanel.Children.Add(textBox);
}
// etc for other types you care about
}
window.ShowDialog();
Console.WriteLine("Airline is now {0}",request.Airline);
Console.WriteLine("Finished");
}
}
class TripRequest
{
public string Airline { get; set; }
public int Price { get; set; }
}