in
Forums
Blogs
Files
Devexpress.Com
ClientCenter
Support Center
DevExpress Channel

The One With

Silverlight : More than one default template in generic.xaml?

I was working on something recently that required more than one default template. In other words the default template to be used by a control was determined by another property.

For example, suppose you have a Control called Shape

public enum ShapeType {
Red,
Black,
}

public class Shape : Control {
public Shape() {
this.DefaultStyleKey = typeof(Shape);
}

public ShapeType Type {
get { return (ShapeType)GetValue(TypeProperty); }
set { SetValue(TypeProperty, value); }
}
}

with a default style:

<Style TargetType="local:Shape">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:Shape">
<Rectangle Fill="Red"></Rectangle>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

and you want the template to change based on the ShapeType. This is simple to do just by looking up the template from the resource dictionary.

First thing to do is to refactor the generic.xaml a little bit so that different control templates are available as resource items.

<ControlTemplate TargetType="local:Shape" x:Key="Shape:Black">
<Rectangle Fill="Black"></Rectangle>
</ControlTemplate>

<ControlTemplate TargetType="local:Shape" x:Key="Shape:Red">
<Rectangle Fill="Red"></Rectangle>
</ControlTemplate>

<Style TargetType="local:Shape">
<Setter Property="Template" Value="{StaticResource Shape:Red}"></Setter>
</Style>

The initial value for the Template is the same as the default value for the ShapeType enum.

Then, when the value of the Type changes, we will look up the control template:

public static readonly DependencyProperty TypeProperty =
DependencyProperty.Register("Type", typeof(ShapeType), typeof(Shape), new PropertyMetadata(new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) {
Shape s = d as Shape;
if (s != null) {
s.OnShapeTypeChanged(true);
}

})));

 

private string GetTemplateName(ShapeType type) {
switch (type) {
case ShapeType.Red:
return "Shape:Red";
case ShapeType.Black:
return "Shape:Black";
default:
return null;
}
}
protected void OnShapeTypeChanged(bool applyTemplate) {
ResourceDictionary genericXaml = ResourceManager.GetResourceDictionary(null);
if (genericXaml == null) {
this.Template = null;
return;
}
string templateName = GetTemplateName(this.Type);
if (string.IsNullOrEmpty(templateName)) {
this.Template = null;
return;
}
this.Template = genericXaml[templateName] as ControlTemplate;
if (applyTemplate) {
this.ApplyTemplate();
}
}

An additional helper class ResourceManager:

internal static class ResourceManager {
private static Dictionary<string, ResourceDictionary> _resourceDictionaryCache =
new Dictionary<string, ResourceDictionary>();

/// <summary>
/// GetResourceDictionary
/// </summary>
public static ResourceDictionary GetResourceDictionary(string name) {
var resourceName = name;
if (string.IsNullOrEmpty(resourceName)) {
resourceName = "generic.xaml";
}
ResourceDictionary retVal = null;
if (_resourceDictionaryCache.TryGetValue(resourceName, out retVal)) {
return retVal;
}
System.Reflection.Assembly assembly = typeof(ResourceManager).Assembly;
string baseName = string.Format("{0}.g",
assembly.FullName.Split(new char[] { ',' })[0]);
string fullName = string.Format("{0}.resources", baseName);
foreach (string s in assembly.GetManifestResourceNames()) {
if (s == fullName) {
System.Resources.ResourceManager manager =
new System.Resources.ResourceManager(baseName, assembly);
using (System.IO.Stream stream = manager.GetStream(resourceName)) {
using (System.IO.StreamReader reader = new System.IO.StreamReader(stream)) {
retVal = System.Windows.Markup.XamlReader.Load(reader.ReadToEnd()) as ResourceDictionary;
if (retVal != null) {
_resourceDictionaryCache.Add(resourceName, retVal);
return retVal;
}
}
}
break;
}
}
return null;
}
}

And that's it.

 

Cheers,

Azret

Published Jul 29 2008, 12:17 PM by Azret Botash (Developer Express)
Filed under:
Technorati tags: Silverlight

Comments

 

Valentin said:

Hm... this seems too complex for such a simple thing.

Aren't there simpler method for doing this in Silverlight?

July 29, 2008 3:50 PM
 

WorkSight Blog » Blog Archive » Closable TabItem said:

Pingback from  WorkSight Blog  » Blog Archive   » Closable TabItem

September 22, 2008 2:01 PM

Leave a Comment

(required)  
(optional)
(required)  
Verification code: Required
   
Add
Copyright © 1998-2008 Developer Express Inc.
ALL RIGHTS RESERVED