Search code examples
c#wpfbindattached-properties

How to bind AttachedProperty


I have created Attached Property, for learning purposes but can't get successful result.

 public class AQDatagridDependencyProperties: DependencyObject
{
    public static void SetCustomDataSource(AQDataGrid element, string value)
    {
        element.SetValue(CustomDataSourceProperty, value);
    }

    public static string GetCustomDataSource(AQDataGrid element)
    {
        return (string)element.GetValue(CustomDataSourceProperty);
    }

    // Using a DependencyProperty as the backing store for DataSource.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CustomDataSourceProperty =
        DependencyProperty.Register("CustomDataSource", typeof(string), typeof(AQDataGrid), new PropertyMetadata("obuolys"));

}

I've placed this attached property in my custom datagrid User Control which is implemented in UserView Page.

<Page x:Class="PDB.UsersView"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  xmlns:local="clr-namespace:PDB"
  xmlns:PDB ="clr-namespace:PDBapi;assembly=PDBapi"
  xmlns:Wpf ="clr-namespace:AQWpf;assembly=AQWpf"
  mc:Ignorable="d" 
  d:DesignHeight="450" d:DesignWidth="800"
  Title="Users"
  Name="Users"
  VisualBitmapScalingMode="LowQuality"

  >

<Page.DataContext>
    <PDB:UsersViewModel x:Name="vm"/>
</Page.DataContext>

<Grid VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling">
    <Wpf:AQDataGrid DataContext="{Binding AQDatagridViewModel}" Wpf:AQDatagridDependencyProperties.CustomDataSource="Something" />
</Grid>

Question is how to bind that attached property value inside Custom Datagrid User Control? Example:

<UserControl x:Class="AQWpf.AQDataGrid"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:AQWpf"
         xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
         mc:Ignorable="d"              
         Name="AQCustomDataGrid"

         >
<!--Custom Data grid Implementation-->

    <DataGrid x:Name="InstructionsDataGrid" 
              Grid.Row="1"
              DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=local:AQDataGrid}, Path=DataContext}"
              Style="{StaticResource OptimizedAGDatagrid}"
              ItemsSource="{Binding Data}"
              CurrentItem="{Binding SelectedObject, Mode=TwoWay}"
              CurrentColumn="{Binding CurrentColumn, Mode=TwoWay}"
              CurrentCell="{Binding CurrentCells, Mode=TwoWay}"  
              Tag="<----How to bind here? ---->}"
              >

Solution

  • Your attached property declaration is incorrect. You must call RegisterAttached instead of Register, and the third argument passed to the method must by the type of the class that declares the property.

    Besides that, the declaring class does not need to be derived from DependencyObject, and could even be declared static:

    public static class AQDatagridDependencyProperties
    {
        public static readonly DependencyProperty CustomDataSourceProperty =
             DependencyProperty.RegisterAttached( // here
                 "CustomDataSource",
                 typeof(string),
                 typeof(AQDatagridDependencyProperties), // and here
                 new PropertyMetadata("obuolys"));
    
        public static string GetCustomDataSource(AQDataGrid element)
        {
            return (string)element.GetValue(CustomDataSourceProperty);
        }
    
        public static void SetCustomDataSource(AQDataGrid element, string value)
        {
            element.SetValue(CustomDataSourceProperty, value);
        }
    } 
    

    You would set that property like

     <local:AQDataGrid local:AQDatagridDependencyProperties.CustomDataSource="something" >
    

    and bind to it by an expression like

    Tag="{Binding Path=(local:AQDatagridDependencyProperties.CustomDataSource),
                  RelativeSource={RelativeSource AncestorType=UserControl}}"
    

    As a note, you would typically declare the property as a regular dependency property in the AQDataGrid class.