This is a migrated thread and some comments may be shown as answers.

Different DraggedElementVisualCueTemplate depending on dragged item type

3 Answers 39 Views
Docking
This is a migrated thread and some comments may be shown as answers.
Andrew
Top achievements
Rank 1
Andrew asked on 05 Sep 2018, 09:04 PM

In RadDock for WPF it is possible to set the DraggedElementVisualCue / DraggedElementVisualCueTemplate when using RadDocking.DragDropMode = Deferred. 

 

<ControlTemplate x:Key="DraggedElementVisualCueTemplate">
    <Grid Width="300" Height="200">
        <Border
            Margin="0 0 4 4"
            CornerRadius="1"
            BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            Background="{TemplateBinding Background}" />
        <Border Margin="0 0 4 4" Padding="10">
            <TextBlock
                Text="{Binding Title}"
                Foreground="{StaticResource IconForegroundLight}"
                Margin="{TemplateBinding Padding}"
                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Border>
    </Grid>
</ControlTemplate>
 
<docking:ObjectToTypeStringConverter x:Key="ObjectToTypeStringConverter"/>
 
<Style TargetType="telerik:DraggedElementVisualCue">
    <Setter Property="Foreground" Value="{StaticResource IconForegroundLight}"/>
    <Setter Property="BorderBrush" Value="{DynamicResource AccentColorBrush}"/>
    <Setter Property="Background" Value="{StaticResource HeaderBackgroundBrush}"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="BorderThickness" Value="2"/>
    <Setter Property="Margin" Value="10 0 0 0"/>
    <Setter Property="Padding" Value="6 2"/>
</Style>

 

So far so good :) 

What I'd like to do is to is have a different VisualCue template for certain pane types (e.g. depending on DataContext type, or Pane Type itself) 

Any ideas how? 

DraggedElementVisualCue.DataContext is of type DockingDragDropPayload. There is a Pane property in there but it's private ... so the data exists just not accessible. 

3 Answers, 1 is accepted

Sort by
0
Andrew
Top achievements
Rank 1
answered on 05 Sep 2018, 09:06 PM

Edit: That Style is missing a line to apply the template 

<Style TargetType="telerik:DraggedElementVisualCue">
       <Setter Property="Foreground" Value="{StaticResource IconForegroundLight}"/>
       <Setter Property="BorderBrush" Value="{DynamicResource AccentColorBrush}"/>
       <Setter Property="Background" Value="{StaticResource HeaderBackgroundBrush}"/>
       <Setter Property="HorizontalContentAlignment" Value="Center"/>
       <Setter Property="VerticalContentAlignment" Value="Center"/>
       <Setter Property="BorderThickness" Value="2"/>
       <Setter Property="Margin" Value="10 0 0 0"/>
       <Setter Property="Padding" Value="6 2"/>
       <Setter Property="Template" Value="{StaticResource DraggedElementVisualCueTemplate}"/>
   </Style>
0
Andrew
Top achievements
Rank 1
answered on 06 Sep 2018, 10:37 AM

So I have a solution but it's a hack. I wonder if anyone can improve on it? 

Telerik support could improve by making DockingDragDropPayload.Pane and PaneGroup fields public get-only properties

Here's my code

public class DockingDragDropPayloadEx
    {
        private readonly DockingDragDropPayload _payload;
        private RadPane _pane;
        private RadPaneGroup _paneGroup;
 
        public DockingDragDropPayloadEx(DockingDragDropPayload payload)
        {
            _payload = payload;
            var fields = _payload.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
            //var names = fields.Select(x => x.Name).ToArray();
            var paneField = fields.First(x => x.Name.Contains("Pane"));
            var paneGroupField = fields.First(x => x.Name.Contains("PaneGroup"));
            _pane = (paneField.GetValue(_payload) as WeakReference)?.Target as RadPane;
            _paneGroup = (paneGroupField.GetValue(_payload) as WeakReference)?.Target as RadPaneGroup;
        }
 
        public object Title => _payload.Title;
 
        public RadPane Pane => _pane;
 
        public bool IsDocumentPane => _pane is RadDocumentPane || _paneGroup?.ChildrenOfType<RadDocumentPane>().Count() > 0;
 
        public bool IsWorkspacePane => _pane is RadWorkspacePane || _paneGroup?.ChildrenOfType<RadWorkspacePane>().Count() > 0;
 
        public static implicit operator DockingDragDropPayload(DockingDragDropPayloadEx d)
        {
            return d._payload;
        }
    }
 
    public class DragDropPayloadFetcher
    {
        public static readonly DependencyProperty FetchPaneFromDataContextProperty = DependencyProperty.RegisterAttached(
            "FetchPaneFromDataContext", typeof(bool), typeof(DragDropPayloadFetcher), new PropertyMetadata(default(bool), OnFetchPaneFromDataContextPropertyChanged));
 
        private static void OnFetchPaneFromDataContextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var cue = ((DraggedElementVisualCue) d);
            var payload = cue.DataContext as DockingDragDropPayload;
            cue.Tag = new DockingDragDropPayloadEx(payload);           
        }
 
        public static void SetFetchPaneFromDataContext(DependencyObject element, bool value)
        {
            element.SetValue(FetchPaneFromDataContextProperty, value);
        }
 
        public static bool GetSetFetchPaneFromDataContext(DependencyObject element)
        {
            return (bool) element.GetValue(FetchPaneFromDataContextProperty);
        }
    }

 

And the style becomes

<ControlTemplate x:Key="DocumentVisualCueTemplate">
    <Grid Width="300" Height="200">
        <Border
            Margin="0 0 4 4"
            CornerRadius="1"
            BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            Background="Green"/>
        <Border Margin="0 0 4 4" Padding="10">
            <TextBlock
                Text="{Binding Title}"
                Foreground="{StaticResource IconForegroundLight}"
                Margin="{TemplateBinding Padding}"
                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Border>
    </Grid>
</ControlTemplate>
 
<ControlTemplate x:Key="WorkspaceVisualCueTemplate">
    <Grid Width="300" Height="200">
        <Border
            Margin="0 0 4 4"
            CornerRadius="1"
            BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            Background="{TemplateBinding Background}" />
        <Border Margin="0 0 4 4" Padding="10">
            <TextBlock
                Text="{Binding Title}"
                Foreground="{StaticResource IconForegroundLight}"
                Margin="{TemplateBinding Padding}"
                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Border>
    </Grid>
</ControlTemplate>
 
<Style TargetType="telerik:DraggedElementVisualCue">
    <Setter Property="docking:DragDropPayloadFetcher.FetchPaneFromDataContext" Value="True"/>
    <Setter Property="Foreground" Value="{StaticResource IconForegroundLight}"/>
    <Setter Property="BorderBrush" Value="{DynamicResource AccentColorBrush}"/>
    <Setter Property="Background" Value="{StaticResource HeaderBackgroundBrush}"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="BorderThickness" Value="2"/>
    <Setter Property="Margin" Value="10 0 0 0"/>
    <Setter Property="Padding" Value="6 2"/>
    <Style.Triggers>
        <DataTrigger Binding="{Binding Tag.IsDocumentPane, RelativeSource={RelativeSource Self}}" Value="True">
            <DataTrigger.Setters>
                <Setter Property="Template" Value="{StaticResource DocumentVisualCueTemplate}"/>
            </DataTrigger.Setters>
        </DataTrigger>
        <DataTrigger Binding="{Binding Tag.IsWorkspacePane, RelativeSource={RelativeSource Self}}" Value="True">
            <DataTrigger.Setters>
                <Setter Property="Template" Value="{StaticResource WorkspaceVisualCueTemplate}"/>
            </DataTrigger.Setters>
        </DataTrigger>
    </Style.Triggers>
</Style>

 

 

 

0
Martin
Telerik team
answered on 10 Sep 2018, 03:59 PM
Hello Andrew,

Thank you for the provided solution to the community. Another approach to achieve the desired behavior is to add DragInitialize handler through DragDropManager and get the dragged item. After that to continue your solution and set it to tag property of VisualCue. You can take a look for the code snippet below for the reference: 
public MainWindow()
      {
          InitializeComponent();
          DragDropManager.AddDragInitializeHandler(this, OnDragInit, true);
      }
 
      private void OnDragInit(object sender, DragInitializeEventArgs e)
      {
          if (e.OriginalSource is PaneHeader)
          {
              var type = DragDropPayloadManager.GetDataFromObject(e.Data, typeof(RadPaneGroup).Name);
              var type2 = DragDropPayloadManager.GetDataFromObject(e.Data, typeof(RadPane).Name);
 
              var dragVisual = e.DragVisual as DraggedElementVisualCue;
 
              dragVisual.Tag = "";
               
          }  
      }

I hope that this helps.

Regards,
Martin Vatev
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Tags
Docking
Asked by
Andrew
Top achievements
Rank 1
Answers by
Andrew
Top achievements
Rank 1
Martin
Telerik team
Share this question
or