Points to be covered:
Create a user control to simplify WPF forms.
First define a style in your resource file:
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="{Binding Orientation, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type uc:MyDataForm}}}"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type uc:MyDataForm}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ItemsPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="ConfirmationTemplate" TargetType="{x:Type uc:MyDataFormItem}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Margin}">
<DockPanel LastChildFill="False">
<TextBlock Style="{DynamicResource TextGray13BoldLbl}" DockPanel.Dock="Top" Margin="10,1,0,0" Text="{Binding Path=(uc:MyDataFormItem.LabelText)}" />
<ContentPresenter Margin="10,0,0,0" />
</DockPanel>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="EntryFormTemplate" TargetType="{x:Type uc:MyDataFormItem}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Margin}">
<DockPanel LastChildFill="False">
<Label Style="{StaticResource NewDesignFormInputLabelStyle}" DockPanel.Dock="Bottom" Margin="5,1,0,0"
Content="{Binding Path=(uc:MyDataFormItem.LabelText), Converter={StaticResource UpperCaseConv}}" />
<ContentPresenter Margin="2,0,0,0" />
</DockPanel>
</Border>
</ControlTemplate>
<Style TargetType="{x:Type uc:MyDataFormItem}">
<Setter Property="Template" Value="{StaticResource EntryFormTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(uc:MyDataFormItem.IsConfirmation)}" Value="True">
<Setter Property="Template" Value="{StaticResource ConfirmationTemplate}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Visibility}" Value="Collapsed">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type uc:MyDataFormItem}">
<Border Visibility="Collapsed"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
- 1. Create a user control to simplify WPF forms. (this post)
- 2. Use Strategy pattern in a complex decision making scenario.
- 3. Converters
- 4. Create a template to make form creations faster
- 5. Create a common print template to print all forms in WPF
Create a user control to simplify WPF forms.
First define a style in your resource file:
<!---MyDataForm Related Styles-->
<Style TargetType="{x:Type uc:MyDataForm}"> <Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="{Binding Orientation, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type uc:MyDataForm}}}"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type uc:MyDataForm}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ItemsPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="ConfirmationTemplate" TargetType="{x:Type uc:MyDataFormItem}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Margin}">
<DockPanel LastChildFill="False">
<TextBlock Style="{DynamicResource TextGray13BoldLbl}" DockPanel.Dock="Top" Margin="10,1,0,0" Text="{Binding Path=(uc:MyDataFormItem.LabelText)}" />
<ContentPresenter Margin="10,0,0,0" />
</DockPanel>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="EntryFormTemplate" TargetType="{x:Type uc:MyDataFormItem}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Margin}">
<DockPanel LastChildFill="False">
<Label Style="{StaticResource NewDesignFormInputLabelStyle}" DockPanel.Dock="Bottom" Margin="5,1,0,0"
Content="{Binding Path=(uc:MyDataFormItem.LabelText), Converter={StaticResource UpperCaseConv}}" />
<ContentPresenter Margin="2,0,0,0" />
</DockPanel>
</Border>
</ControlTemplate>
<Style TargetType="{x:Type uc:MyDataFormItem}">
<Setter Property="Template" Value="{StaticResource EntryFormTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(uc:MyDataFormItem.IsConfirmation)}" Value="True">
<Setter Property="Template" Value="{StaticResource ConfirmationTemplate}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Visibility}" Value="Collapsed">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type uc:MyDataFormItem}">
<Border Visibility="Collapsed"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
Then create a class MyDataForm which is a user control:
public class MyDataForm : ItemsControl
{ static MyDataForm()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyDataForm), new FrameworkPropertyMetadata(typeof(MyDataForm)));
IsTabStopProperty.OverrideMetadata(typeof(MyDataForm), new FrameworkPropertyMetadata(false));
}
public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(MyDataForm), new FrameworkPropertyMetadata(Orientation.Vertical));
public Orientation Orientation
{
get { return (Orientation)GetValue(OrientationProperty); }
set
{
SetValue(OrientationProperty, value);
}
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is MyDataForm || item is MyDataFormItem;
}
protected override DependencyObject GetContainerForItemOverride()
{
return new MyDataFormItem();
}
}
Then create a class MyDataFormItem which is a user control:
public class MyDataFormItem : ContentControl
{ static MyDataFormItem()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyDataFormItem), new FrameworkPropertyMetadata(typeof(MyDataFormItem)));
IsTabStopProperty.OverrideMetadata(typeof(MyDataFormItem), new FrameworkPropertyMetadata(false));
}
public static readonly DependencyProperty LabelTextProperty = DependencyProperty.RegisterAttached("LabelText", typeof(string), typeof(MyDataFormItem));
public static string GetLabelText(DependencyObject obj)
{
return (string)obj.GetValue(LabelTextProperty);
}
public static void SetLabelText(DependencyObject obj, string value)
{
obj.SetValue(LabelTextProperty, value);
}
public static bool GetIsConfirmation(DependencyObject obj)
{
return (bool)obj.GetValue(IsConfirmationProperty);
}
public static void SetIsConfirmation(DependencyObject obj, bool value)
{
obj.SetValue(IsConfirmationProperty, value);
}
// Using a DependencyProperty as the backing store for IsConfirmation. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsConfirmationProperty =
DependencyProperty.RegisterAttached("IsConfirmation", typeof(bool), typeof(MyDataFormItem), new UIPropertyMetadata(false));
}
Usage in XAML
<TextBox uc:MyDataFormItem.LabelText="Contact name" x:Name="txtContactName" Text="{Binding ContactName}" TextWrapping="Wrap"></TextBox>
Other points covered in other posts