I am still pretty new to creating DependencyProperties and extending other controls in WPF.
I have extended a ContentControl which I want to use as a DialogHeader, I am following how I have done this in the past, but maybe I am not doing it right:
This is what I have:
DialogHeader.cs
public static class DialogHeader
{
static DialogHeader()
{
AllowDraggingProperty = AllowDraggingPropertyKey.DependencyProperty;
}
#region - AllowDragging -
public static readonly DependencyProperty AllowDraggingProperty;
private static readonly DependencyPropertyKey AllowDraggingPropertyKey =
DependencyProperty.RegisterAttachedReadOnly("AllowDragging", typeof(bool), typeof(DialogHeader),
new PropertyMetadata(false));
public static bool GetAllowDragging(FrameworkElement element)
{
return element is null
? throw new ArgumentNullException(nameof(element))
: (bool)element.GetValue(AllowDraggingProperty);
}
public static void SetAllowDragging(FrameworkElement element, bool value)
{
if (element is null)
throw new ArgumentNullException(nameof(element));
element.SetValue(AllowDraggingProperty, value);
}
#endregion - AllowDragging -
}
ContentControlStyle.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:b="clr-namespace:WpfToolkit.UX.Controls.Behaviors"
xmlns:ux="clr-namespace:WpfToolkit.UX.Controls.Controls">
<ControlTemplate x:Key="DialogHeader" TargetType="{x:Type ContentControl}">
<Border x:Name="bdrOuter"
Height="72"
Style="{DynamicResource DialogHeader.Border}">
<ContentControl x:Name="ccDraggableArea"
Template="{DynamicResource DraggableArea}">
<DockPanel LastChildFill="True"
Margin="4,0">
<Button x:Name="btnClose"
DockPanel.Dock="Right"
Margin="0,6,0,0"
Template="{DynamicResource Close}"
VerticalAlignment="Top" />
<Image x:Name="imgLogo"
DockPanel.Dock="Left"
HorizontalAlignment="Left"
Margin="0,8,8,4"
RenderOptions.BitmapScalingMode="HighQuality"
Source="pack://application:,,,/UX.Themes;component/Assets/Branding/Logo.png"
Stretch="Uniform"
VerticalAlignment="Center" />
<Label x:Name="lblHeading"
Content="Dialog Header"
DockPanel.Dock="Left"
FontFamily="{DynamicResource Inter}"
Foreground="{DynamicResource ForegroundBrush}"
Template="{DynamicResource DialogHeading}"
VerticalAlignment="Center" />
</DockPanel>
</ContentControl>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ux:DialogHeader.AllowDragging" Value="False">
<Setter TargetName="ccDraggableArea" Property="Visibility" Value="Collapsed" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ResourceDictionary>
MainWindow.xaml
<TabItem Header="Window Header/Footer" IsSelected="True">
<Grid Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition MinHeight="100" Height="Auto"/>
<RowDefinition MinHeight="100" Height="Auto"/>
<RowDefinition MinHeight="100" Height="Auto"/>
<RowDefinition MinHeight="100" Height="Auto"/>
</Grid.RowDefinitions>
<ContentControl x:Name="ccHeader"
Grid.Row="0"
Template="{DynamicResource DialogHeader}"
ux:DialogHeader.AllowDragging="False"/>
<ContentControl x:Name="ccHeaderCompact"
Grid.Row="1"
Template="{DynamicResource DialogHeader.Compact}" />
<ContentControl x:Name="ccFooter"
Grid.Row="2"
Template="{DynamicResource DialogFooter}" />
<ContentControl x:Name="ccFooterCompact"
Grid.Row="3"
Template="{DynamicResource DialogFooter.Compact}" />
</Grid>
</TabItem>
What I am in the process of doing is creating our own internal WPF Toolkit of Controls and Templates to be used over a couple of our solutions. As part of this, I am creating a window that shows all of the styles and templates, hence why the MainWindow above has a tab control.
The issue I am facing at the moment is on running the app, I hit this exception:
InvalidOperationException: 'AllowDragging' property was registered as read-only and cannot be modified without an authorization key.
I assume this is caused by the setup I have, but this has worked in other instances where I have implemented this, I have never seen the ReadOnly exception before.
The XAML assignment
<ContentControl ... ux:DialogHeader.AllowDragging="False" />
means that you do not want to create a read-only attached property, so you must not be using DependencyProperty.RegisterAttachedReadOnly
. Use DependencyProperty.RegisterAttached
instead.
This is how your code should look like:
public static class DialogHeader
{
public static readonly DependencyProperty AllowDraggingProperty =
DependencyProperty.RegisterAttached(
"AllowDragging", typeof(bool), typeof(DialogHeader));
public static bool GetAllowDragging(FrameworkElement element)
{
return (bool)element.GetValue(AllowDraggingProperty);
}
public static void SetAllowDragging(FrameworkElement element, bool value)
{
element.SetValue(AllowDraggingProperty, value);
}
}