blend - WPF Attach VisualState to Object Property -
i working on expression blend vs2015, have alistbox
binded observablecollection
of custom objects. objects expose properties
arise notifypropertychanged
, , works nice.
i can bind parts if itemtemplate
properties
, list work nice want set visualstate
according bool
(already configured or not). created events (configured, conflost) , tried target events in triggers panel .. nothing worked.
how bind visualstates
members of bound object ??
itemtemplate
property works other dependencyproperty
, can set/reset anytime , it's visual impact reflected on ui
. see below example have bound bool
value togglebutton
state , itemcontrol's
itemtemplate
changed accordingly rendering different visual
.
update: designed device
class has device name , it's state make similar situation. , class myvisualstatemanager
create bindable property. cause visualstatemanager
class doesn't expose property bind directly. code below:
xmal
<window x:class="wpfstackoverflowtempproject.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" title="mainwindow" width="525" datacontext="{binding relativesource={relativesource mode=self}}" xmlns:local="clr-namespace:wpfstackoverflowtempproject" > <itemscontrol itemssource="{binding list}" > <itemscontrol.itemtemplate> <datatemplate> <local:usercontrol1 datacontext="{binding name}" width="200" borderbrush="black" borderthickness="2" padding="2"> <local:usercontrol1.style> <style targettype="{x:type local:usercontrol1}"> <style.triggers> <datatrigger binding="{binding relativesource={relativesource templatedparent}, path=datacontext.devicestate}" value="0"> <setter property="local:myvisualstatemanager.visualstate" value="state1" /> </datatrigger> <datatrigger binding="{binding relativesource={relativesource templatedparent}, path=datacontext.devicestate}" value="1"> <setter property="local:myvisualstatemanager.visualstate" value="state2" /> </datatrigger> </style.triggers> </style> </local:usercontrol1.style> </local:usercontrol1> </datatemplate> </itemscontrol.itemtemplate> </itemscontrol>
usercontrol:
<usercontrol x:class="wpfstackoverflowtempproject.usercontrol1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:ignorable="d" d:designheight="300" d:designwidth="300"> <grid> <visualstatemanager.visualstategroups> <visualstategroup x:name="common"> <visualstate x:name="state1"> <storyboard> <doubleanimation to="1" duration="0:00:2" storyboard.targetname="state1panel" storyboard.targetproperty="(uielement.opacity)" /> <doubleanimation to="0" duration="0:00:3" storyboard.targetname="state2panel" storyboard.targetproperty="(uielement.opacity)" /> </storyboard> </visualstate> <visualstate x:name="state2"> <storyboard> <doubleanimation to="0" duration="0:00:3" storyboard.targetname="state1panel" storyboard.targetproperty="(uielement.opacity)" /> <doubleanimation to="1" duration="0:00:2" storyboard.targetname="state2panel" storyboard.targetproperty="(uielement.opacity)" /> </storyboard> </visualstate> </visualstategroup> </visualstatemanager.visualstategroups> <border name="state2panel" background="green" opacity="0"/> <border name="state1panel" background="red" opacity="1"/> <textblock text="{binding path=.}" foreground="white" horizontalalignment="center" verticalalignment="center"/> </grid>
datacontext:
public partial class mainwindow : window { public mainwindow() { list = new list<device>(); list.add(new device() {name="device 1",devicestate = 0 }); list.add(new device() { name = "device 2", devicestate = 1 }); list.add(new device() { name = "device 3", devicestate = 0 }); list.add(new device() { name = "device 4", devicestate = 2 }); list.add(new device() { name = "device 5", devicestate = 1 }); initializecomponent(); } public list<device> list { get; set; } } public class device : inotifypropertychanged { private string name; public string name { { return name; } set { name = value; updateproperty("name"); } } private int devicestate; public int devicestate { { return devicestate; } set { devicestate = value; updateproperty("devicestate"); } } public event propertychangedeventhandler propertychanged; public void updateproperty(string name) { if (propertychanged != null) { propertychanged(this, new propertychangedeventargs(name)); } } }
helper class: class exposes attached property visualstate
bound value in xaml
.
public class myvisualstatemanager { public static string getvisualstate(dependencyobject obj) { return (string)obj.getvalue(visualstateproperty); } public static void setvisualstate(dependencyobject obj, string value) { obj.setvalue(visualstateproperty, value); } // using dependencyproperty backing store visualstate. enables animation, styling, binding, etc... public static readonly dependencyproperty visualstateproperty = dependencyproperty.registerattached("visualstate", typeof(string), typeof(myvisualstatemanager), new propertymetadata(new propertychangedcallback(visualstatechanged))); public static void visualstatechanged(dependencyobject do, dependencypropertychangedeventargs e) { if (e.newvalue != null) { string state = e.newvalue.tostring(); var control = frameworkelement; visualstatemanager.gotostate(control, state, true); } } }
output
different item representing different devices , visual changed on basis of their
devicestateproperty causes a
triggerto executed in
usercontrol1.
Comments
Post a Comment