Switch WPF UI at runtime
-
I have a set of data that can be defined by the user, this will consist of item types i provide to them, for example (Text/Date/Decimal/Address/Lookup/Group). A group allows them to put related data together, groups can be nested as deep as the user requires. Think Composite pattern. As every user is able to create their own structure how it is best displayed will also vary from user to user. I would like to be able to provide a mechanism that allows the user to select how they want their data displayed. To do this i have created a ResourceDictionary for each way of displaying the data but i've struggled to find a good way to implement switching between display methods. I have looked into switching the ResourceDictionary in code but could not find a good way to implement this. I've also thought about implementing a DataTemplateSelector and again struggled to get this working. I tried creating empty interfaces (IShowAsTree, IShowAsTabs, IShowAsGroupBoxes), implementing them all in my view that holds the data, and casting when i return the property they are bound to.
public interface IBaseView{}
public interface IShowAsTree:IBaseView{}
public interface IShowAsTabs:IBaseView{}
public interface IShowAsGroupBoxes:IBaseView{}public class DataCollection:BaseVM, IShowAsTree, IShowAsTabs, IShowAsGroupBoxes
{
//extended data class
}public class ExtenededDataView:BaseVM
{
public String[] ViewAsOptions{get{return new[] {"Tree","Tabs","GroupBoxes"}}private String \_viewAs; public String ViewAs { get {return \_viewAs;} set { \_viewAs = value; OnPropertyChanged(()=>View); } } private DataCollection \_view; public IBaseView View { get { switch(ViewAs) { case "Tree": return \_view as IShowTabs; break; //... } } }
}
This failed, should have known but DataTemplating appears to only work on classes not interfaces. This is when i decided on quite a hack for a solution, replace the interfaces with classes, and put a property in the parent class that holds the DataCollection. This works but feels wrong, so if any one can advice me of a better solution, or an area to research more it would be appreciated. Thanks to anyone who read this far, code was typed in so may well contain the odd error, but hop
-
I have a set of data that can be defined by the user, this will consist of item types i provide to them, for example (Text/Date/Decimal/Address/Lookup/Group). A group allows them to put related data together, groups can be nested as deep as the user requires. Think Composite pattern. As every user is able to create their own structure how it is best displayed will also vary from user to user. I would like to be able to provide a mechanism that allows the user to select how they want their data displayed. To do this i have created a ResourceDictionary for each way of displaying the data but i've struggled to find a good way to implement switching between display methods. I have looked into switching the ResourceDictionary in code but could not find a good way to implement this. I've also thought about implementing a DataTemplateSelector and again struggled to get this working. I tried creating empty interfaces (IShowAsTree, IShowAsTabs, IShowAsGroupBoxes), implementing them all in my view that holds the data, and casting when i return the property they are bound to.
public interface IBaseView{}
public interface IShowAsTree:IBaseView{}
public interface IShowAsTabs:IBaseView{}
public interface IShowAsGroupBoxes:IBaseView{}public class DataCollection:BaseVM, IShowAsTree, IShowAsTabs, IShowAsGroupBoxes
{
//extended data class
}public class ExtenededDataView:BaseVM
{
public String[] ViewAsOptions{get{return new[] {"Tree","Tabs","GroupBoxes"}}private String \_viewAs; public String ViewAs { get {return \_viewAs;} set { \_viewAs = value; OnPropertyChanged(()=>View); } } private DataCollection \_view; public IBaseView View { get { switch(ViewAs) { case "Tree": return \_view as IShowTabs; break; //... } } }
}
This failed, should have known but DataTemplating appears to only work on classes not interfaces. This is when i decided on quite a hack for a solution, replace the interfaces with classes, and put a property in the parent class that holds the DataCollection. This works but feels wrong, so if any one can advice me of a better solution, or an area to research more it would be appreciated. Thanks to anyone who read this far, code was typed in so may well contain the odd error, but hop
Im a little confused as to what exactly you are trying to do. Do you want to creat a custom "user control" of sorts?
-
I have a set of data that can be defined by the user, this will consist of item types i provide to them, for example (Text/Date/Decimal/Address/Lookup/Group). A group allows them to put related data together, groups can be nested as deep as the user requires. Think Composite pattern. As every user is able to create their own structure how it is best displayed will also vary from user to user. I would like to be able to provide a mechanism that allows the user to select how they want their data displayed. To do this i have created a ResourceDictionary for each way of displaying the data but i've struggled to find a good way to implement switching between display methods. I have looked into switching the ResourceDictionary in code but could not find a good way to implement this. I've also thought about implementing a DataTemplateSelector and again struggled to get this working. I tried creating empty interfaces (IShowAsTree, IShowAsTabs, IShowAsGroupBoxes), implementing them all in my view that holds the data, and casting when i return the property they are bound to.
public interface IBaseView{}
public interface IShowAsTree:IBaseView{}
public interface IShowAsTabs:IBaseView{}
public interface IShowAsGroupBoxes:IBaseView{}public class DataCollection:BaseVM, IShowAsTree, IShowAsTabs, IShowAsGroupBoxes
{
//extended data class
}public class ExtenededDataView:BaseVM
{
public String[] ViewAsOptions{get{return new[] {"Tree","Tabs","GroupBoxes"}}private String \_viewAs; public String ViewAs { get {return \_viewAs;} set { \_viewAs = value; OnPropertyChanged(()=>View); } } private DataCollection \_view; public IBaseView View { get { switch(ViewAs) { case "Tree": return \_view as IShowTabs; break; //... } } }
}
This failed, should have known but DataTemplating appears to only work on classes not interfaces. This is when i decided on quite a hack for a solution, replace the interfaces with classes, and put a property in the parent class that holds the DataCollection. This works but feels wrong, so if any one can advice me of a better solution, or an area to research more it would be appreciated. Thanks to anyone who read this far, code was typed in so may well contain the odd error, but hop
I don't find the interface approach incorrect. Using interfaces to implement more complex templating sounds like a valid pattern to me.
A new Windows Phone App - Speed Dial
-
Im a little confused as to what exactly you are trying to do. Do you want to creat a custom "user control" of sorts?
I'm trying to allow the user to switch which DataTemplate is used for an object based on a choice by the user. At a very basic level consider an oject you have written called MyObject:
That resource Dictionary provides 3 different DataTemplates for the same object, what i want is a mechanism to let the user pick which one gets used, but in the actual situation things are a little more complex, but once i sort the right way to do the switching then i'll be able to implement that for the more complex situation.
-
I don't find the interface approach incorrect. Using interfaces to implement more complex templating sounds like a valid pattern to me.
A new Windows Phone App - Speed Dial
It did also appear valid to me, but when the data templates were setup with a DataType={x:Type Interfaces:IShowTree}, the template was not applied and the name of the view model was shown. A little google for "DataTemplate Interface" returns lots of results all saying that DataTemplates don't work with interfaces. The main reason seems to be classes that imlement multiple interfaces would be difficult for WPF to pick the right DataTemplate to use.
-
I have a set of data that can be defined by the user, this will consist of item types i provide to them, for example (Text/Date/Decimal/Address/Lookup/Group). A group allows them to put related data together, groups can be nested as deep as the user requires. Think Composite pattern. As every user is able to create their own structure how it is best displayed will also vary from user to user. I would like to be able to provide a mechanism that allows the user to select how they want their data displayed. To do this i have created a ResourceDictionary for each way of displaying the data but i've struggled to find a good way to implement switching between display methods. I have looked into switching the ResourceDictionary in code but could not find a good way to implement this. I've also thought about implementing a DataTemplateSelector and again struggled to get this working. I tried creating empty interfaces (IShowAsTree, IShowAsTabs, IShowAsGroupBoxes), implementing them all in my view that holds the data, and casting when i return the property they are bound to.
public interface IBaseView{}
public interface IShowAsTree:IBaseView{}
public interface IShowAsTabs:IBaseView{}
public interface IShowAsGroupBoxes:IBaseView{}public class DataCollection:BaseVM, IShowAsTree, IShowAsTabs, IShowAsGroupBoxes
{
//extended data class
}public class ExtenededDataView:BaseVM
{
public String[] ViewAsOptions{get{return new[] {"Tree","Tabs","GroupBoxes"}}private String \_viewAs; public String ViewAs { get {return \_viewAs;} set { \_viewAs = value; OnPropertyChanged(()=>View); } } private DataCollection \_view; public IBaseView View { get { switch(ViewAs) { case "Tree": return \_view as IShowTabs; break; //... } } }
}
This failed, should have known but DataTemplating appears to only work on classes not interfaces. This is when i decided on quite a hack for a solution, replace the interfaces with classes, and put a property in the parent class that holds the DataCollection. This works but feels wrong, so if any one can advice me of a better solution, or an area to research more it would be appreciated. Thanks to anyone who read this far, code was typed in so may well contain the odd error, but hop
The easy way to do this is to use a trick I describe here[^]. Basically, you don't show them as
DataTemplate
s. What you do is to convert yourDataTemplate
s intoControlTemplate
s, and then have a singleDataTemplate
that uses DataTriggers to swap templates depending on the underlying data.*pre-emptive celebratory nipple tassle jiggle* - Sean Ewington
"Mind bleach! Send me mind bleach!" - Nagy Vilmos
CodeStash - Online Snippet Management | My blog | MoXAML PowerToys | Mole 2010 - debugging made easier