Points to be covered:
FormTemplate here is a user control just like a master page, with dependency properties, placeholders for consumer views and common controls
Create a FormTemplate user control class like this:
InputControlsPlaceHolder is an example placeholder where the consumer will have to provide controls.
FormTitle is a property bound to a label in the usercontrol xaml, which consumers can set it.
{
public EntryFormTemplate()
{
Initialize();
}
private void Initialize()
{
ResourceDictionary resources = new ResourceDictionary();
resources.Source = new Uri("Resources/FormTemplate.xaml", UriKind.Relative);
this.Resources = resources;
}
public object InputControlsPlaceHolder
{
get { return (object)GetValue(InputControlsPlaceHolderProperty); }
set { SetValue(InputControlsPlaceHolderProperty, value); }
}
// Using a DependencyProperty as the backing store for InputControlsPlaceHolder. This enables animation, styling, binding, etc...
public static readonly DependencyProperty InputControlsPlaceHolderProperty =
DependencyProperty.Register("InputControlsPlaceHolder", typeof(object), typeof(EntryFormTemplate), new UIPropertyMetadata(""));
public string FormTitle
{
get { return (string)GetValue(FormTitleProperty); }
set { SetValue(FormTitleProperty, value); }
}
// Using a DependencyProperty as the backing store for FormTitle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FormTitleProperty =
DependencyProperty.Register("FormTitle", typeof(string), typeof(EntryFormTemplate), new UIPropertyMetadata("Enter some title here."));
}
- 1. Create a user control to simplify WPF forms.(covered in previous post)
- 2. Use Strategy pattern in a complex decision making scenario.
- 3. Converters (this post) (covered in previous post)
- 4. Create a template to make form creations faster (this post)
- 5. Create a common print template to print all forms in WPF
FormTemplate here is a user control just like a master page, with dependency properties, placeholders for consumer views and common controls
Create a FormTemplate user control class like this:
InputControlsPlaceHolder is an example placeholder where the consumer will have to provide controls.
FormTitle is a property bound to a label in the usercontrol xaml, which consumers can set it.
public class EntryFormTemplate : UserControl
{
public EntryFormTemplate()
{
Initialize();
}
private void Initialize()
{
ResourceDictionary resources = new ResourceDictionary();
resources.Source = new Uri("Resources/FormTemplate.xaml", UriKind.Relative);
this.Resources = resources;
}
public object InputControlsPlaceHolder
{
get { return (object)GetValue(InputControlsPlaceHolderProperty); }
set { SetValue(InputControlsPlaceHolderProperty, value); }
}
// Using a DependencyProperty as the backing store for InputControlsPlaceHolder. This enables animation, styling, binding, etc...
public static readonly DependencyProperty InputControlsPlaceHolderProperty =
DependencyProperty.Register("InputControlsPlaceHolder", typeof(object), typeof(EntryFormTemplate), new UIPropertyMetadata(""));
public string FormTitle
{
get { return (string)GetValue(FormTitleProperty); }
set { SetValue(FormTitleProperty, value); }
}
// Using a DependencyProperty as the backing store for FormTitle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FormTitleProperty =
DependencyProperty.Register("FormTitle", typeof(string), typeof(EntryFormTemplate), new UIPropertyMetadata("Enter some title here."));
}
Now you need to add this XAML file as a resource (explaination given at the end of this post):
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!--All your common styles should be placed here-->
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextBoxStyle}">
<Style.Setters>
<Setter Property="MinWidth" Value="100"></Setter>
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(uc:DataFormItem.LabelText), diag:PresentationTraceSources.TraceLevel=High}"/>
</Style.Setters>
</Style>
<!--Converters-->
<conv:RadioConverter x:Key="enumConverter" />
<Style TargetType="{x:Type uc:FormTemplate}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type uc:FormTemplate}">
<Grid>
<StackPanel>
<Label Style="{StaticResource TitleLabelStyle}" Content="{Binding FormTitle, FallbackValue=Title, RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type uc:FormTemplate}}}"/>
<ScrollViewer>
<ContentControl Height="auto" Content="{Binding InputControlsPlaceHolder, RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type uc:FormTemplate}}}"/>
<!--Also include all common controls here with their bindings-->
</ScrollViewer>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Why was this done
Why did we put the style in resource file and not in a user control XAML?
You cannot use named controls inside a user control which will be consumed by other views (this was the issue faced) The workaround was to create a user control class and give it a look by loading the style from the resource dictionary. Define your placeholder dependency properties here.
<ContentControl Height="auto" Content="{Binding InputControlsPlaceHolder, RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type uc:FormTemplate}}}"/> Why is this done?
Relative source is important here. We will provide the controls for input placeholder in the consumer view, but we'll also have to take care that the properties of those controls will have the consumer VM as its data source.
No comments :
Post a Comment