c# - Binding to DynamicObjects in XAML in WinRT -
i have observablecollection<dynamic>
class , xaml refuses bind properties on contained objects.
i know read somewhere xaml supports dynamic
, dyanmicobject
i'm mightily confused on why not working. other questions, such one, spectacularly un-helpful:
can bind against dynamicobject in winrt / windows 8 store apps
i error @ runtime (and in designer @ design time when hovering on {binding
s):
error: bindingexpression path error: 'displayname' property not found on 'premisemetro.light, premisemetro, ... bindingexpression: path='displayname' dataitem='premisemetro.light, premisemetro, ... target element 'windows.ui.xaml.controls.textblock' (name='null'); target property 'text' (type 'string')
please help!
thanks.
a test observableobject
class:
class light : dynamicobject, inotifypropertychanged { private readonly dictionary<string, object> _properties = new dictionary<string, object>(); public event propertychangedeventhandler propertychanged; public override bool trygetmember(getmemberbinder binder, out object result) { string name = binder.name; result = null; // if property name found in dictionary, // set result parameter property value , return true. // otherwise, return false. object prop; if (_properties.trygetvalue(name, out prop)) { result = prop; return true; } return false; } // if try set value of property // not defined in class, method called. public override bool trysetmember(setmemberbinder binder, object value) { string name = binder.name; _properties[name] = value; if (coreapplication.mainview.corewindow.dispatcher.hasthreadaccess) onpropertychanged(name); else coreapplication.mainview.corewindow.dispatcher.runasync( coredispatcherpriority.normal, () => onpropertychanged(name)); // can add value dictionary, // method returns true. return true; } public object getmember(string propname) { var binder = binder.getmember(csharpbinderflags.none, propname, gettype(), new list<csharpargumentinfo> { csharpargumentinfo.create(csharpargumentinfoflags.none, null) }); var callsite = callsite<func<callsite, object, object>>.create(binder); return callsite.target(callsite, this); } /// <summary> /// sets value of property. /// </summary> /// <param name="propertyname">name of property</param> /// <param name="val">new value</param> /// <param name="fromserver">if true, not try update server.</param> public void setmember(string propertyname, object val) { var binder = binder.setmember(csharpbinderflags.none, propertyname, gettype(), new list<csharpargumentinfo> { csharpargumentinfo.create(csharpargumentinfoflags.none, null), csharpargumentinfo.create(csharpargumentinfoflags.none, null) }); var callsite = callsite<func<callsite, object, object, object>>.create(binder); callsite.target(callsite, this, val); } protected virtual void onpropertychanged(string propertyname) { propertychangedeventhandler handler = propertychanged; if (handler != null) handler(this, new propertychangedeventargs(propertyname)); } }
a test in mainviewmodel constructor:
light light = new light(); ((dynamic) light).displayname = "test light"; ((dynamic) light).brightness= "27%"; ((dynamic) light).powerstate= false; lights = new observablecollection<dynamic> { light };
my test xaml:
<grid margin="10" width="1000" verticalalignment="stretch"> <listbox x:name="gdolist" itemssource="{binding path=lights}" > <listbox.itemtemplate> <datatemplate > <grid margin="6"> <stackpanel orientation="horizontal" > <textblock text="{binding path=displayname}" margin="5" /> <textblock text="{binding path=powerstate}" margin="5" /> <textblock text="{binding path=brightness}" margin="5" /> </stackpanel> </grid> </datatemplate> </listbox.itemtemplate> </listbox> </grid> </page>
can try changing viewmodel to:
dynamic light = new expandoobject(); light.displayname = "test light"; light.brightness = "27%"; light.powerstate = false; var objs = new observablecollection<dynamic> { light };
and see if works in lib correctly?
Comments
Post a Comment