D&D functionality for Radgrid to Textbox control

8 posts, 0 answers
  1. sudhesh
    sudhesh avatar
    6 posts
    Member since:
    Dec 2008

    Posted 11 Sep 2013 Link to this post

    Hi All,

      i have a requirement to implement d&d functionality for radgridview(only drag) to textBox (only drop) control.so i tried the drag and drop demo application comes with the telerik suite. gridview to listbox is working fine and the problem is don't know how to implement for textbox control and textbox value should be either one of the dragging column of gridview in MVVM pattern.

       
    <UserControl x:Class="TelerikDragandDrop.MainWindow"
            xmlns:telerikDragandDrop="clr-namespace:TelerikDragandDrop">
     
        <UserControl.Resources>
            <telerikDragandDrop:MainViewModel x:Key="ViewModel"/>
     
             
            <!--Note: With this style we make the ListBoxItems draggable:-->
            <Style TargetType="ListBoxItem" x:Key="WishlistItemStyle" >
                <Setter Property="telerik:DragDropManager.AllowCapturedDrag" Value="True" />
                <Setter Property="telerik:DragDropManager.TouchDragTrigger" Value="TapAndHold"/>
            </Style>
            <Style TargetType="telerik:GridViewRow" x:Key="OrderItemStyle" >
                <Setter Property="telerik:DragDropManager.AllowCapturedDrag" Value="True" />
                <Setter Property="telerik:DragDropManager.TouchDragTrigger" Value="TapAndHold"/>
            </Style>
     
            <Style TargetType="{x:Type TextBox}" x:Key="textBoxStyle">
                <Setter Property="telerik:DragDropManager.AllowCapturedDrag" Value="False" />
                <Setter Property="telerik:DragDropManager.TouchDragTrigger" Value="TapAndHold"/>
                <Setter Property="Foreground" Value="#777777" />
            </Style>
             
        </UserControl.Resources>
        <Grid x:Name="LayoutRoot">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
     
            
     
            <!--Order-->
            <Border BorderBrush="#C8C9CC" BorderThickness="2" CornerRadius="6" Margin="46 46 0 46"
                    Background="White" Grid.Column="1">
                <DockPanel>
                    <Border DockPanel.Dock="Top"
                            Background="{telerik:Windows8Resource ResourceKey=AccentBrush}" CornerRadius="4 4 0 0">
                        <TextBlock Text="Order" Foreground="{telerik:Windows8Resource ResourceKey=MainBrush}" Margin="20 5 5 5" FontSize="14" />
                    </Border>
                    <!--NOTE: The GridView is a drop target, we set the AllowDrop to true.-->
                    <telerik:RadGridView x:Name="orderView" IsReadOnly="True" Grid.Column="1" Grid.Row="0" Margin="0,0,0,5"
                                         RowIndicatorVisibility="Collapsed" GroupRenderMode="Flat" ItemsSource="{Binding AllApplications, Source={StaticResource ViewModel}}"
                                         RowStyle="{StaticResource OrderItemStyle}" CanUserFreezeColumns=" False" CanUserInsertRows="False"
                                         CanUserReorderColumns="False" CanUserSortColumns="False" ShowGroupPanel="False" Padding="5" AllowDrop="True"
                                         telerikDragandDrop:GridViewDragDropBehavior.IsEnabled="True" Height="115">
                        <telerik:RadGridView.Resources>
                             
                            <DataTemplate x:Key="DraggedItemTemplate">
                                <StackPanel>
                                    <StackPanel Orientation="Horizontal">
                                        <TextBlock Text="Dragging:"/>
                                        <TextBlock Text="{Binding CurrentDraggedItem.FirstName}" FontWeight="Bold"/>
                                    </StackPanel>
                                     
                                </StackPanel>
                            </DataTemplate>
                        </telerik:RadGridView.Resources>
                    </telerik:RadGridView>
                </DockPanel>
            </Border>
     
            <!--Whishlist-->
            <Border BorderBrush="#C8C9CC" BorderThickness="2" CornerRadius="6" Margin="46"
                    Background="White" Grid.Column="2">
                <DockPanel>
                    <Border DockPanel.Dock="Top"
                            Background="{telerik:Windows8Resource ResourceKey=AccentBrush}" CornerRadius="4 4 0 0">
                        <TextBlock Text="Wishlist" Margin="20 5 5 5" Foreground="{telerik:Windows8Resource ResourceKey=MainBrush}" FontSize="14" />
                    </Border>
                    <!--NOTE: The ListBox is a drop target, we set the AllowDrop to true.-->
                    <ListBox x:Name="wishlistView" Grid.Column="1" Grid.Row="1"
                             SelectionMode="Extended"
                             ItemsSource="{Binding MyApplications, Source={StaticResource ViewModel}}" FontSize="11"
                          
                             ItemContainerStyle="{StaticResource WishlistItemStyle}" Padding="5" AllowDrop="True"
                             telerikDragandDrop:ListBoxDragDropBehavior.IsEnabled="True"
                             telerik:TouchManager.IsTouchHitTestVisible="True">
                        <ListBox.Resources>
                           
                            <DataTemplate x:Key="DraggedItemTemplate">
                                <StackPanel>
                                    <StackPanel Orientation="Horizontal">
                                        <TextBlock Text="Dragging:"/>
                                        <TextBlock Text="{Binding CurrentDraggedItem.FirstName}" FontWeight="Bold"/>
                                    </StackPanel>
                                   
                                </StackPanel>
                                 
                            </DataTemplate>
                        </ListBox.Resources>
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <Grid Width="150">
                                    <Grid.RowDefinitions>
                                        <RowDefinition />
                                        <RowDefinition />
                                        <RowDefinition />
                                    </Grid.RowDefinitions>
                                   <TextBlock Grid.Row="1" Text="{Binding FirstName}" FontWeight="Bold"
                                       HorizontalAlignment="Center" Foreground="#FF767676"/>
                                    <TextBlock Text="{Binding LastName}" Grid.Row="2"
                                       HorizontalAlignment="Center" Foreground="#FF767676"/>
                                </Grid>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </DockPanel>
            </Border>
            <TextBox Height="35" Name="TextBox1" Style="{StaticResource textBoxStyle}"  AllowDrop="True"   Width="225" Grid.Column="2" Margin="24,204,13,8"   telerikDragandDrop:TextBoxDragDropBehaviour.IsEnabled="True"  telerik:TouchManager.IsTouchHitTestVisible="True" />
        </Grid>
    </UserControl>
    public class TextBoxDragDropBehaviour
       {
           private TextBox _associatedObject;
     
           /// <summary>
           /// AssociatedObject Property
           /// </summary>
           public TextBox AssociatedObject
           {
               get
               {
                   return _associatedObject;
               }
               set
               {
                   _associatedObject = value;
               }
           }
     
           private static Dictionary<TextBox, TextBoxDragDropBehaviour> instances;
     
           static TextBoxDragDropBehaviour()
           {
               instances = new Dictionary<TextBox, TextBoxDragDropBehaviour>();
           }
     
           public static bool GetIsEnabled(DependencyObject obj)
           {
               return (bool)obj.GetValue(IsEnabledProperty);
           }
     
           public static void SetIsEnabled(DependencyObject obj, bool value)
           {
               TextBoxDragDropBehaviour behavior = GetAttachedBehavior(obj as TextBox );
     
               behavior.AssociatedObject = obj as TextBox;
     
               if (value)
               {
                   behavior.Initialize();
               }
               else
               {
                   behavior.CleanUp();
               }
               obj.SetValue(IsEnabledProperty, value);
           }
     
           // Using a DependencyProperty as the backing store for IsEnabled.  This enables animation, styling, binding, etc...
           public static readonly DependencyProperty IsEnabledProperty =
               DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(TextBoxDragDropBehaviour),
                   new PropertyMetadata(new PropertyChangedCallback(OnIsEnabledPropertyChanged)));
           public static void OnIsEnabledPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
           {
               SetIsEnabled(dependencyObject, (bool)e.NewValue);
           }
     
           private static TextBoxDragDropBehaviour GetAttachedBehavior(TextBox listBox)
           {
               if (!instances.ContainsKey(listBox))
               {
                   instances[listBox] = new TextBoxDragDropBehaviour();
                   instances[listBox].AssociatedObject = listBox;
               }
     
               return instances[listBox];
           }
     
           protected virtual void Initialize()
           {
               this.UnsubscribeFromDragDropEvents();
               this.SubscribeToDragDropEvents();
           }
     
           protected virtual void CleanUp()
           {
               this.UnsubscribeFromDragDropEvents();
           }
     
           private void SubscribeToDragDropEvents()
           {
               DragDropManager.AddDragInitializeHandler(this.AssociatedObject, OnDragInitialize);
               DragDropManager.AddGiveFeedbackHandler(this.AssociatedObject, OnGiveFeedback);
               DragDropManager.AddDropHandler(this.AssociatedObject, OnDrop);
               DragDropManager.AddDragDropCompletedHandler(this.AssociatedObject, OnDragDropCompleted);
               DragDropManager.AddDragOverHandler(this.AssociatedObject, OnDragOver);
           }
     
           private void UnsubscribeFromDragDropEvents()
           {
               DragDropManager.RemoveDragInitializeHandler(this.AssociatedObject, OnDragInitialize);
               DragDropManager.RemoveGiveFeedbackHandler(this.AssociatedObject, OnGiveFeedback);
               DragDropManager.RemoveDropHandler(this.AssociatedObject, OnDrop);
               DragDropManager.RemoveDragDropCompletedHandler(this.AssociatedObject, OnDragDropCompleted);
               DragDropManager.RemoveDragOverHandler(this.AssociatedObject, OnDragOver);
           }
     
           private void OnDragInitialize(object sender, DragInitializeEventArgs e)
           {
               DropIndicationDetails details = new DropIndicationDetails();
               var listBoxItem = e.OriginalSource as System.Windows.Controls.ListBoxItem ?? (e.OriginalSource as FrameworkElement).ParentOfType<System.Windows.Controls.ListBoxItem>();
     
               var textBox = sender as System.Windows.Controls.TextBox;
               if (textBox != null)
               {
                   var item = listBoxItem != null ? listBoxItem.DataContext : textBox.Text;
                   details.CurrentDraggedItem = item;
     
                   IDragPayload dragPayload = DragDropPayloadManager.GeneratePayload(null);
     
                   dragPayload.SetData("DraggedData", item);
                   dragPayload.SetData("DropDetails", details);
     
                   e.Data = dragPayload;
               }
     
               e.DragVisual = new DragVisual()
               {
                   Content = details,
                   ContentTemplate = this.AssociatedObject.Resources["DraggedItemTemplate"] as DataTemplate
               };
               e.DragVisualOffset = e.RelativeStartPoint;
               e.AllowedEffects = DragDropEffects.All;
           }
     
           private void OnGiveFeedback(object sender, Telerik.Windows.DragDrop.GiveFeedbackEventArgs e)
           {
               e.SetCursor(Cursors.Arrow);
               e.Handled = true;
           }
     
           private void OnDragDropCompleted(object sender, DragDropCompletedEventArgs e)
           {
               var draggedItem = DragDropPayloadManager.GetDataFromObject(e.Data, "DraggedData");
     
               if (e.Effects != DragDropEffects.None)
               {
                   //var collection = (sender as TextBox).Text;
                   //collection.Remove(draggedItem);
               }
           }
     
           private void OnDrop(object sender, Telerik.Windows.DragDrop.DragEventArgs e)
           {
               var draggedItem = DragDropPayloadManager.GetDataFromObject(e.Data, "DraggedData");
               var details = DragDropPayloadManager.GetDataFromObject(e.Data, "DropDetails") as DropIndicationDetails;
               var itemsType = (this.AssociatedObject.Text);
     
               //if (details == null || draggedItem == null || draggedItem.GetType() != itemsType)
               //{
               //    return;
               //}
     
               if (e.Effects != DragDropEffects.None)
               {
                   var collection = (sender as TextBox);
                   if (collection != null) collection.Text = collection.Text;
               }
           }
     
           private void OnDragOver(object sender, Telerik.Windows.DragDrop.DragEventArgs e)
           {
               //var draggedItem = DragDropPayloadManager.GetDataFromObject(e.Data, "DraggedData");
               //var itemsType = (this.AssociatedObject.ItemsSource as IList).AsQueryable().ElementType;
     
               //if (draggedItem.GetType() != itemsType)
               //{
               //    e.Effects = DragDropEffects.None;
               //}
     
               //var dropDetails = DragDropPayloadManager.GetDataFromObject(e.Data, "DropDetails") as DropIndicationDetails;
               //dropDetails.CurrentDraggedOverItem = this.AssociatedObject;
               //dropDetails.CurrentDropPosition = Controls.DropPosition.Inside;
     
               e.Handled = true;
           }
       }
  2. Yoan
    Admin
    Yoan avatar
    1068 posts

    Posted 16 Sep 2013 Link to this post

    Hello sudhesh,

    I have prapared a sample project showing you how to drop into the textbox. You can find the demo project attached. Please examine it and let me know if it fits in your scenario.

    Regards,
    Yoan
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  3. UI for WPF is Visual Studio 2017 Ready
  4. David
    David avatar
    27 posts
    Member since:
    Apr 2013

    Posted 22 May 2014 Link to this post

    This example appears to do exactly what I want. I even modified it to have the grid view and textbox in different windows within the same app and it still works. Unfortunately the exact same thing does not work in my app which is way to large to split out and I have been unable to reproduce my error. Just wondered if anyone knew the answer right off or could point me in the right direction, could save me a lot of time (already wasted several hours on this). 

    I am trying to drag a row from a grid view to a text box. I am dragging a row (actually the object the row is bound to) from the grid and the text box has to look at the object and determine whether it can be dropped and how to drop it. The problem is that the text box's OnDrop event does not get called unless the drop payload has a Text entry in it. I don't want a Text entry in it because I am not dragging text and I end up being able to drop these objects in all kinds of places that I should not. Also, the default behavior is wrong, how the text should be displayed in the textbox is different based on the drop target. Note that my DragEnter, DragLeave, DragOver events all get called fine. I tried setting handledEvents to true when registering the event handler with the DragDropManager and I tried using Preview events. OnDrop is never called. If I add a Text entry to the payload OnDrop gets called fine.

    Your example does not appear to be adding the Text entry to the payload but it works. Can anyone think of something I might be doing differently?

    Thanks
    Dave Goughnour...







  5. Nick
    Admin
    Nick avatar
    593 posts

    Posted 23 May 2014 Link to this post

    Hi David,

    The TextBox in WPF has an internal Drag and Drop behavior that is very hard to override. In order to be able to drop in it you have to set a "Text" data in your payload/DataObject.

    Hope this helps. 

    Regards,
    Nik
    Telerik
     
    Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
     
  6. David
    David avatar
    27 posts
    Member since:
    Apr 2013

    Posted 23 May 2014 Link to this post

    Thanks, this is more out of curiosity but the thing that confused me is that the example referenced above does not appear to include Text in the payload and it works. Am I missing something?

    I can put Text in the payload in my app I just have to go around to other places and add code to exclude dropping this Text where it does not belong. Kind of ugly but it works.

    I am actually thinking a cleaner solution might be to write my own textbox...

    Thanks again
    Dave Goughnour
  7. Nick
    Admin
    Nick avatar
    593 posts

    Posted 28 May 2014 Link to this post

    Hi David,

    The project that is included in the thread is overriding the TextBox's drag drop functionality in the TextBoxDragDropBehavior class. It basically sets the text of the TextBox to the ToString value if the dragged object. 

    Hope this helps. 

    Regards,
    Nik
    Telerik
     
    Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
     
  8. David
    David avatar
    27 posts
    Member since:
    Apr 2013

    Posted 28 May 2014 in reply to Nick Link to this post

    I did exactly the same thing in my app. I 'borrowed' the TextBoxDragDropBehavior class and used it in my app. The behavior's drop handler was only called if I added a Text entry to my drag payload. But the sample does not seem to be adding a Text entry. In fact the sample's payload looks almost exactly like the one in my app (different classes obviously). But in my app the target's drop handler is not called unless I also add a Text entry. Again, more of a curiosity at this point but I still don't understand what I am doing different.
  9. Nick
    Admin
    Nick avatar
    593 posts

    Posted 30 May 2014 Link to this post

    Hi David,

    The problem is that the TextBox's internal drag drop logic sets the DragEffects to none if there is no Text present, and therefore the logic in the Drop event is not executed. 

    Hope this helps. 

    Regards,
    Nik
    Telerik
     
    Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
     
Back to Top
UI for WPF is Visual Studio 2017 Ready