Reputation: 5384
In WPF, I have a Canvas to which I am drawing horizontal lines across the background, something like a notepad with ruled lines. The spacing of these lines is bound to the viewmodel. The below code works well.
I now would like to convert the canvas, its background, and the applied behavior into a single customcontrol. The basic problem, ofcourse, is that a Canvas does not have a Template property, so TemplateBinding from Generic.XAML is out.
How can this be done? Any help or suggestions is most appreciated.
TIA
XAML
<!--This style used to draw background lines on the notepad canvas.-->
<Style x:Key="notepadLines" TargetType="{x:Type Canvas}">
<Setter Property="Background">
<Setter.Value>
<DrawingBrush Stretch="None" TileMode="Tile" ViewportUnits="Absolute">
<DrawingBrush.Viewport>
<MultiBinding>
<MultiBinding.Converter>
<conv:RectConverter/>
</MultiBinding.Converter>
<Binding Path="WritingLayer.MainCanvas.ViewPortWidth"/>
<Binding Path="WritingLayer.MainCanvas.ViewPortHeight"/>
</MultiBinding>
</DrawingBrush.Viewport>
<DrawingBrush.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<GeometryDrawing>
<GeometryDrawing.Brush>
<SolidColorBrush Color="Purple" Opacity="0.2" />
</GeometryDrawing.Brush>
<GeometryDrawing.Pen>
<Pen Thickness="1" Brush="LightGreen"/>
</GeometryDrawing.Pen>
<GeometryDrawing.Geometry>
<RectangleGeometry>
<RectangleGeometry.Rect>
<MultiBinding>
<MultiBinding.Converter>
<conv:DrawingBoxConverter/>
</MultiBinding.Converter>
<Binding Path="WritingLayer.MainCanvas.DrawingBoxTop"/>
<Binding Path="WritingLayer.MainCanvas.ViewPortWidth"/>
<Binding Path="WritingLayer.MainCanvas.DrawingBoxHeight"/>
</MultiBinding>
</RectangleGeometry.Rect>
</RectangleGeometry>
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing>
<GeometryDrawing.Geometry>
<GeometryGroup>
<LineGeometry StartPoint="0,0" EndPoint="{Binding WritingLayer.MainCanvas.EndPointHeight}"/>
<LineGeometry StartPoint="0,0" EndPoint="{Binding WritingLayer.MainCanvas.EndPointWidth}"/>
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Thickness="1" Brush="Green"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
<GeometryDrawing>
<GeometryDrawing.Geometry>
<GeometryGroup>
<LineGeometry StartPoint="{Binding WritingLayer.MainCanvas.StartPointMidline}"
EndPoint="{Binding WritingLayer.MainCanvas.EndPointMidline}"/>
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Thickness="1" Brush="Red">
<Pen.DashStyle>
<DashStyle Dashes="4,12"/>
</Pen.DashStyle>
</Pen>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingGroup.Children>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Setter.Value>
</Setter>
</Style>
<Canvas x:Name="NotePad" Grid.Column="1" Grid.Row="1"
Visibility="{Binding WritingLayer.IsWriting, Converter={StaticResource BoolToVisibilityConverter}}"
Style="{StaticResource notepadLines}"
>
<i:Interaction.Behaviors>
<b:NotePadBackgroundBehavior/>
</i:Interaction.Behaviors>
</Canvas>
Upvotes: 1
Views: 378
Reputation: 5384
O.K, made a few changes. The below does compile correctly:
<Style TargetType="{x:Type local:NotePad}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:NotePad">
<Canvas>
<Canvas.Background>
<DrawingBrush Stretch="None" TileMode="Tile" ViewportUnits="Absolute">
<DrawingBrush.Viewport>
<MultiBinding>
<MultiBinding.Converter>
<conv:RectConverter/>
</MultiBinding.Converter>
<Binding Path="{TemplateBinding ViewPortWidth}"/>
<Binding Path="{TemplateBinding ViewPortHeight}"/>
</MultiBinding>
</DrawingBrush.Viewport>
........................................................
public class NotePad : Control
{
static NotePad()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(NotePad), new FrameworkPropertyMetadata(typeof(NotePad)));
}
#region [ViewPortWidth]
public double ViewPortWidth
{
get { return (double)GetValue(ViewPortWidthProperty); }
set { SetValue(ViewPortWidthProperty, value); }
}
// Using a DependencyProperty as the backing store for ViewPortWidth. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ViewPortWidthProperty =
DependencyProperty.Register("ViewPortWidth", typeof(double), typeof(NotePad), new PropertyMetadata(0.0));
#endregion
Upvotes: 0
Reputation: 169150
Create a custom control that has a Canvas
in its ControlTemplate
.
Generic.xaml:
<Style TargetType="local:CustomControl">
<Setter Property="Template">
<Setter.Value>
<Canvas>
<Canvas.Background>
<DrawingBrush Stretch="None" TileMode="Tile" ViewportUnits="Absolute">
...
</DrawingBrush>
</Canvas.Background>
</Canvas>
</Setter.Value>
</Setter>
</Style>
Control:
public class CustomControl : Control
{
static CustomControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl),
new FrameworkPropertyMetadata(typeof(CustomControl)));
}
//... + any properties...
}
Usage:
<local:CustomControl />
Upvotes: 1