Bin4ry
Bin4ry

Reputation: 732

WPF Bind DependencyProperty to another DependencyProperty

I have a TreeView within a UserControl, which is able to Scroll + Zoom and Drag. (Because the TreeView is really huge) Because the Scroll/Zoom/Drag UserControl is listening to

  1. OnScrollViewerScrollChanged
  2. OnMouseLeftButtonUp
  3. OnMouseLeftButtonUp
  4. OnPreviewMouseWheel
  5. OnMouseLeftButtonDown
  6. OnMouseMove

the TreeViewItems are not able to receive any mouse input. Therefore, I created a DependencyProperty for a TreeViewItem, so called IsMouseHover. That DP toggles between true and false, if the mouse enters or leaves the TreeViewItem.

The ScrollZoomDrag UserControl also has a DP, so called "Active", which subscribes or unsubscribes all the mentioned events above.

Now I would like to bind the TreeViewItem's "IsMouseHover" to the ScrollZoomDrag's Control "Active" DP.

    <controls:ScrollDragZoomControl>
    <controls:OrgTreeView ItemsSource="{Binding Root}">
        <controls:OrgTreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Children, Mode=TwoWay}">
                <controls:VisualElement DataContext="{Binding}">
                    <Style TargetType="controls:ScrollDragZoomControl">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=controls:VisualElement}, Path=IsMouseHover}" Value="True">
                                <Setter Property="Active" Value="False" />
                            </DataTrigger>
                            <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=controls:VisualElement}, Path=IsMouseHover}" Value="False">
                                <Setter Property="Active" Value="True" />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </controls:VisualElement>
            </HierarchicalDataTemplate>
        </controls:OrgTreeView.ItemTemplate>
    </controls:OrgTreeView>
</controls:ScrollDragZoomControl>

With the solution above, the ScrollZoomDrag's DP "Active" doesn't get toggled at all. Am I missing something or is there a better approach?

UPDATE

ScrollZoomDrag.xaml.cs

        public static readonly DependencyProperty ActiveProperty = DependencyProperty.Register("Active", typeof(bool), typeof(ScrollDragZoomControl), new PropertyMetadata(true, new PropertyChangedCallback(ActiveChanged)));

    public bool Active
    {
        get { return (bool)GetValue(ActiveProperty); }
        set { SetValue(ActiveProperty, value); }
    }

    public static void ActiveChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
    {
        ScrollDragZoomControl scrollDragZoomControl = (ScrollDragZoomControl)obj;

        if ((bool)args.NewValue)
            scrollDragZoomControl.StartListen();
        else scrollDragZoomControl.StopListen();
    }

VisualElement.xaml.cs

        public static readonly DependencyProperty IsMouseHoverProperty = DependencyProperty.Register("IsMouseHover", typeof(bool), typeof(VisualElement), new PropertyMetadata(false));

    public VisualElement()
    {
        InitializeComponent();
        MouseEnter += VisualElement_MouseEnter;
        MouseLeave += VisualElement_MouseLeave;
    }

    public bool IsMouseHover
    {
        get { return (bool)GetValue(IsMouseHoverProperty); }
        set { SetValue(IsMouseHoverProperty, value); }
    }

    private void VisualElement_MouseLeave(object sender, MouseEventArgs e)
    {
        IsMouseHover = false;
    }

    private void VisualElement_MouseEnter(object sender, MouseEventArgs e)
    {
        IsMouseHover = true;
    }

Approach 2: (Doesn't work either)

    <controls:ScrollDragZoomControl>
    <controls:ScrollDragZoomControl.Style>
        <Style TargetType="controls:ScrollDragZoomControl">
            <Style.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=controls:VisualElement}, Path=IsMouseHover}" Value="True">
                    <Setter Property="Active" Value="False" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </controls:ScrollDragZoomControl.Style>
    <controls:OrgTreeView ItemsSource="{Binding Root}"
                          HorizontalAlignment="Center"
                          VerticalAlignment="Center">
        <controls:OrgTreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Children, Mode=TwoWay}">
                <controls:VisualElement DataContext="{Binding}">                   
                </controls:VisualElement>
            </HierarchicalDataTemplate>
        </controls:OrgTreeView.ItemTemplate>
    </controls:OrgTreeView>
</controls:ScrollDragZoomControl>

Upvotes: 1

Views: 1494

Answers (2)

ASh
ASh

Reputation: 35681

try a binding with Mode=OneWayToSource :

IsMouseHover="{Binding RelativeSource={RelativeSource AncestorType=controls:ScrollDragZoomControl}, 
                       Path=Active, Mode=OneWayToSource}"
<controls:ScrollDragZoomControl>
  <controls:OrgTreeView ItemsSource="{Binding Root}">
    <controls:OrgTreeView.ItemTemplate>
       <HierarchicalDataTemplate ItemsSource="{Binding Children, Mode=TwoWay}">
         <controls:VisualElement DataContext="{Binding}" 
             IsMouseHover="{Binding RelativeSource={RelativeSource AncestorType=controls:ScrollDragZoomControl}, 
                                    Path=Active, Mode=OneWayToSource}">
         </controls:VisualElement>
      </HierarchicalDataTemplate>
    </controls:OrgTreeView.ItemTemplate>
  </controls:OrgTreeView>
</controls:ScrollDragZoomControl>

Upvotes: 1

ivica.moke
ivica.moke

Reputation: 1064

Maybe to set that Active property binds TwoWay by default so it can register every change

new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

Im not sure, but maybe it helps to notify the change, or you need to set it in xaml mode=TwoWay

Upvotes: 0

Related Questions