Search code examples
c#wpfxamldependency-propertiesdependencyobject

Dependency Property not set from style


I'm trying to synchronize scrolling between two datagrids so that each scroll is mirrored between them (either horizontal or vertical scrolling), after googling around how to do I started to implement my method but the setter call from my scrollbar style never calls the dependency object to set the value.

This is my data grid.

<dataGridEx:DataGridEx ColumnHeaders="{Binding SystemMonitorValues.ColumnHeaders}"
                       ItemsSource="{Binding SystemMonitorValues.Rows}"
                       Style="{StaticResource DataGridStyle}"
                       ScrollViewer.CanContentScroll="True"
                       ScrollViewer.VerticalScrollBarVisibility="Auto"
                       ScrollViewer.HorizontalScrollBarVisibility="Auto">
    <dataGridEx:DataGridEx.Resources>
        <Style TargetType="{x:Type ScrollBar}">
            <Setter Property="Background" Value="Red"/>
            <Setter Property="scroll:ScrollSynchronizer.ScrollGroup" Value="Group1" />
        </Style>
    </dataGridEx:DataGridEx.Resources>
</dataGridEx:DataGridEx>

So within the scroll bar style I am attempting to set the ScrollSynchronizer.ScrollGroup to have the value "Group1".

My ScrollSynchronizer is setup as follows:

public class ScrollSynchronizer : DependencyObject
{
    public static readonly DependencyProperty ScrollGroupProperty = DependencyProperty.Register(@"ScrollGroup",
            typeof(string), typeof(ScrollSynchronizer), new PropertyMetadata(new PropertyChangedCallback(OnScrollGroupChanged)));

static ScrollSynchronizer()
{
}

public string ScrollGroup
{
    get
    {
        return (string)this.GetValue(ScrollGroupProperty);
    }

    set
    {
        this.SetValue(ScrollGroupProperty, value);
    }
}

private static void OnScrollGroupChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var scrollViewer = d as System.Windows.Controls.ScrollViewer;

    ...
}

I'm placing a breakpoint within the OnScrollGroupChanged method which is the PropertyChangedCallback for the DependencyProperty but for some reason this is never hit.

I know the style is working as the background of the scrollbar is being set to Red but the setter for the ScrollGroup doesn't seem to want to be called, this is also shown in Snoop in that the Style is correctly set with the two setters and even the setter for the ScrollSynchronizer point's to the correct object.

I'm simply at a loss to why this is not being set.


Solution

  • ScrollSynchronizer.ScrollGroup should be an attached property instead of a regular dependency property:

    public static class ScrollSynchronizer
    {
        public static readonly DependencyProperty ScrollGroupProperty =
            DependencyProperty.RegisterAttached(
                "ScrollGroup", typeof(string), typeof(ScrollSynchronizer),
                new PropertyMetadata(OnScrollGroupChanged));
    
        public static string GetScrollGroup(DependencyObject obj)
        {
            return (string)obj.GetValue(ScrollGroupProperty);
        }
    
        public static void SetScrollGroup(DependencyObject obj, string value)
        {
            obj.SetValue(ScrollGroupProperty, value);
        }
    
        private static void OnScrollGroupChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var scrollBar = d as ScrollBar;
            ...
        }
    }
    

    Note also that the DependencyObject parameter of the PropertyChangedCallback is of type ScrollBar when you set the property in a ScrollBar Style.