Hi,
Instead of the more usual technical question, this post is related to functional requirements, and choosing among different implementations. I hope I can keep it as short as possible, not too philosophical, and of course, raise interest/curiosity among some of you ;-)
We are currently building a Framework in order to ease and speed up the development of certain kind of applications. We have decided to create a custom control library (using telerik as base) that must fulfill the following requirementes:
1.- Provide just the properties/events (Controls) that we consider necessary. --hiding attributes--
2.- Extend the base controls in order to add extra functionallity. --creating new attributes--
3.- Ease the implementation of our interfaces. By dragging a control from the VisualStudio (or Blend) designer toolbox to the window/page/usercontrol/etc, the developer will have most of the necessary attributes (see req. 1) with the proper default values.
4.- The controls must support all the standard (graphic) features of WPF: Styling, Control Templates, Storyboards, etc.
5.- The controls must support standard event handling, although we might use a fancier action/commanding approach (like the ones implemented by Prism, or Caliburn)
6.- DataBindings.
After some research, we came up with three solutions (summarized, as I'm trying to keep this as short as possible):
A) Wrapping the control: using Control as base class, we add the telerik control as the first (and only) visual child. Then we create a DependencyProperty for each DP we want to expose from the telerik control.
(its much more elaborated, and I didn't copy all the code, but you get the basic idea)
B) Control templating: using Control as base class, we redefine the default styles of each control. The template (ControlTemplate) property is assigned to the telerik control. Then we create a TemplateBinding (or complete Binding, depends...) for each DP we want to expose. The DP is also created in the Control:
(again, its much more elaborated)
C) Directly inheriting the telerik control. (we loose the req. 1, hiding attributes)
In summary:
- Solution A (wrapper) is somehow ugly, and uses a lot of tricks in order to do things such as:
- Creating data bindings (from XAML)
- Using CustomTemplates (from the final developer point of view)
- Create data bindings from code behind.
- Solution B is more elegant (they are pretty much the same thing, as they generate the same logical tree for each control), but I'm not sure how difficult it will be to wrap complex controls, such as the GridView, Ribbon, etc.
- Solution C basically breaks with one of the initial requirements, but its still a valid approach. Besides, you can somehow suggest what properties to use by implementing the Extensibility Model for the WPF Designer.
My questions are:
* What is the best approach, given the scenario I exposed?
* Any other ideas/suggestions?
By the way, we need to provide the same control libraries for Silverlight and ASP.net, and it would be nice to use the same approach, at least with WPF and SL.
Thanks,
--
R.
Instead of the more usual technical question, this post is related to functional requirements, and choosing among different implementations. I hope I can keep it as short as possible, not too philosophical, and of course, raise interest/curiosity among some of you ;-)
We are currently building a Framework in order to ease and speed up the development of certain kind of applications. We have decided to create a custom control library (using telerik as base) that must fulfill the following requirementes:
1.- Provide just the properties/events (Controls) that we consider necessary. --hiding attributes--
2.- Extend the base controls in order to add extra functionallity. --creating new attributes--
3.- Ease the implementation of our interfaces. By dragging a control from the VisualStudio (or Blend) designer toolbox to the window/page/usercontrol/etc, the developer will have most of the necessary attributes (see req. 1) with the proper default values.
4.- The controls must support all the standard (graphic) features of WPF: Styling, Control Templates, Storyboards, etc.
5.- The controls must support standard event handling, although we might use a fancier action/commanding approach (like the ones implemented by Prism, or Caliburn)
6.- DataBindings.
After some research, we came up with three solutions (summarized, as I'm trying to keep this as short as possible):
A) Wrapping the control: using Control as base class, we add the telerik control as the first (and only) visual child. Then we create a DependencyProperty for each DP we want to expose from the telerik control.
public class MyComboBox : MyBaseControl |
{ |
static MyComboBox() |
{ |
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyComboBox), new FrameworkPropertyMetadata(typeof(MyComboBox))); |
RegisterDependencyProperties(typeof(MyComboBox), typeof(RadComboBox)); |
} |
public MyComboBox() |
{ |
InternalFrameworkElement = new RadButton(); |
this.AddVisualChild(InternalFrameworkElement); |
} |
protected override int VisualChildrenCount |
{ |
get |
{ |
return InternalFrameworkElement == null ? 0 : 1; |
} |
} |
protected override Visual GetVisualChild(int index) |
{ |
if (InternalFrameworkElement == null) |
{ |
throw new ArgumentOutOfRangeException(); |
} |
return InternalFrameworkElement; |
} |
private RadComboBox ComboBox |
{ |
get |
{ |
return InternalFrameworkElement as RadComboBox; |
} |
} |
public IEnumerable ItemsSource |
{ |
get { return (IEnumerable)GetValue(ItemsSourceProperty); } |
set { SetValue(ItemsSourceProperty, value); } |
} |
public static readonly DependencyProperty ItemsSourceProperty = |
DependencyProperty.Register( |
"ItemsSource", typeof(IEnumerable), typeof(MyComboBox), |
new FrameworkPropertyMetadata |
{ |
PropertyChangedCallback = (obj, e) => |
{ |
(obj as MyComboBox).UpdateItemsSource((IEnumerable)e.NewValue); |
} |
}); |
private void UpdateItemsSource(IEnumerable sel) |
{ |
ComboBox.ItemsSource = sel; |
} |
} |
B) Control templating: using Control as base class, we redefine the default styles of each control. The template (ControlTemplate) property is assigned to the telerik control. Then we create a TemplateBinding (or complete Binding, depends...) for each DP we want to expose. The DP is also created in the Control:
<Setter Property="Template"> |
<Setter.Value> |
<ControlTemplate TargetType="{x:Type local:MyComboBox}"> |
<ControlsInput:RadComboBox Name="PART_MyComboBox" |
BorderBrush="{TemplateBinding Property=BorderBrush}" |
BorderThickness="{TemplateBinding Property=BorderThickness}" |
Background="{TemplateBinding Property=Background}" |
Foreground="{TemplateBinding Property=Foreground}" |
SelectionBoxTemplate="{TemplateBinding Property=SelectionBoxTemplate}" |
ItemTemplate="{TemplateBinding Property=ItemTemplate}" |
SelectedItem="{Binding RelativeSource={RelativeSource FindAncestor, |
AncestorType={x:Type local:MyComboBox}}, Path=SelectedItem}" |
ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, |
AncestorType={x:Type local:MyComboBox}}, Path=ItemsSource}"> |
</ControlsInput:RadComboBox> |
</ControlTemplate> |
</Setter.Value> |
</Setter> |
C) Directly inheriting the telerik control. (we loose the req. 1, hiding attributes)
public class MyComboBox : RadComboBox |
{ |
static MyComboBox() |
{ |
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyComboBox), new FrameworkPropertyMetadata(typeof(MyComboBox))); |
} |
} |
In summary:
- Solution A (wrapper) is somehow ugly, and uses a lot of tricks in order to do things such as:
- Creating data bindings (from XAML)
- Using CustomTemplates (from the final developer point of view)
- Create data bindings from code behind.
- Solution B is more elegant (they are pretty much the same thing, as they generate the same logical tree for each control), but I'm not sure how difficult it will be to wrap complex controls, such as the GridView, Ribbon, etc.
- Solution C basically breaks with one of the initial requirements, but its still a valid approach. Besides, you can somehow suggest what properties to use by implementing the Extensibility Model for the WPF Designer.
My questions are:
* What is the best approach, given the scenario I exposed?
* Any other ideas/suggestions?
By the way, we need to provide the same control libraries for Silverlight and ASP.net, and it would be nice to use the same approach, at least with WPF and SL.
Thanks,
--
R.