English 中文(简体)
Cannot drag activities from WPF ListBox into WorkflowView
原标题:

I m trying to host the Workflow Designer in a WPF application. The WorkflowView control is hosted under a WindowsFormsHost control. I ve managed to load workflows onto the designer which is successfully linked to a PropertyGrid, also hosted in another WindowsFormsHost.

WorkflowView workflowView = rootDesigner.GetView(ViewTechnology.Default) as WorkflowView;
window.WorkflowViewHost.Child = workflowView;

The majority of the rehosting code is the same as in http://msdn.microsoft.com/en-us/library/aa480213.aspx.

I ve created a custom Toolbox using a ListBox WPF control bound to a list of ToolboxItems.

<ListBox Grid.Row="1" Margin="0 0 0 4" BorderThickness="1" BorderBrush="DarkGray" ItemsSource="{Binding Path=ToolboxItems}" PreviewMouseLeftButtonDown="ListBox_PreviewMouseLeftButtonDown" AllowDrop="True">
 <ListBox.Resources>
  <vw:BitmapSourceTypeConverter x:Key="BitmapSourceConverter" />
 </ListBox.Resources>
 <ListBox.ItemTemplate>
  <DataTemplate DataType="{x:Type dd:ToolboxItem}">
   <StackPanel Orientation="Horizontal" Margin="3">
    <Image Source="{Binding Path=Bitmap, Converter={StaticResource BitmapSourceConverter}}" Height="16" Width="16" Margin="0 0 3 0"     />
    <TextBlock Text="{Binding Path=DisplayName}" FontSize="14" Height="16" VerticalAlignment="Center" />
    <StackPanel.ToolTip>
     <TextBlock Text="{Binding Path=Description}" />
    </StackPanel.ToolTip>
   </StackPanel>
  </DataTemplate>
 </ListBox.ItemTemplate>
</ListBox>

In the ListBox_PreviewMouseLeftButtonDown handler:

private void ListBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
 ListBox parent = (ListBox)sender;

 UIElement dataContainer;
 //get the ToolboxItem for the selected item
 object data = GetObjectDataFromPoint(parent, e.GetPosition(parent), out dataContainer);

 //if the data is not null then start the drag drop operation
 if (data != null)
 {
  DataObject dataObject = new DataObject();
  dataObject.SetData(typeof(ToolboxItem), data);

  DragDrop.DoDragDrop(parent, dataObject, DragDropEffects.Move | DragDropEffects.Copy);
 }
}

With that setup, I m unable to drag any item from my custom Toolbox onto the designer. The cursor is always displayed as "No" anywhere on the designer.

I ve been trying to find anything about this on the net for half a day now and I really hope some can help me here.

Any feedback is much appreciated. Thank you!

Carlos

最佳回答

Finally got Drag and Drop working. There were three things that needed doing, for whatever reason WorkflowView has:

1.) I had to use System.Windows.Forms.DataObject instead of System.Windows.DataObject when serializing the ToolboxItem when doing DragDrop.

private void ListBox_MouseDownHandler(object sender, MouseButtonEventArgs e)
{
    ListBox parent = (ListBox)sender;

    //get the object source for the selected item
    object data = GetObjectDataFromPoint(parent, e.GetPosition(parent));

    //if the data is not null then start the drag drop operation
    if (data != null)
    {
        System.Windows.Forms.DataObject dataObject = new System.Windows.Forms.DataObject();
        dataObject.SetData(typeof(ToolboxItem), data as ToolboxItem);
        DragDrop.DoDragDrop(this, dataObject, DragDropEffects.Move | DragDropEffects.Copy);
    }
}

2.) DragDrop.DoDragDrop source must be set to the IToolboxService set in the IDesignerHost. The control holding the ListBox implements IToolboxService.

// "this" points to ListBox s parent which implements IToolboxService.
DragDrop.DoDragDrop(this, dataObject, DragDropEffects.Move | DragDropEffects.Copy);

3.) The ListBox should be bound to a list of ToolboxItems returned by the following helper method, passing it the Type of the activities to show in the tool box:

...
this.ToolboxItems = new ToolboxItem[] 
    {
        GetToolboxItem(typeof(IfElseActivity))
    };
...

internal static ToolboxItem GetToolboxItem(Type toolType)
{
    if (toolType == null)
        throw new ArgumentNullException("toolType");

    ToolboxItem item = null;
    if ((toolType.IsPublic || toolType.IsNestedPublic) && typeof(IComponent).IsAssignableFrom(toolType) && !toolType.IsAbstract)
    {
        ToolboxItemAttribute toolboxItemAttribute = (ToolboxItemAttribute)TypeDescriptor.GetAttributes(toolType)[typeof(ToolboxItemAttribute)];
        if (toolboxItemAttribute != null && !toolboxItemAttribute.IsDefaultAttribute())
        {
            Type itemType = toolboxItemAttribute.ToolboxItemType;
            if (itemType != null)
            {
                // First, try to find a constructor with Type as a parameter.  If that
                // fails, try the default constructor.
                ConstructorInfo ctor = itemType.GetConstructor(new Type[] { typeof(Type) });
                if (ctor != null)
                {
                    item = (ToolboxItem)ctor.Invoke(new object[] { toolType });
                }
                else
                {
                    ctor = itemType.GetConstructor(new Type[0]);
                    if (ctor != null)
                    {
                        item = (ToolboxItem)ctor.Invoke(new object[0]);
                        item.Initialize(toolType);
                    }
                }
            }
        }
        else if (!toolboxItemAttribute.Equals(ToolboxItemAttribute.None))
        {
            item = new ToolboxItem(toolType);
        }
    }
    else if (typeof(ToolboxItem).IsAssignableFrom(toolType))
    {
        // if the type *is* a toolboxitem, just create it..
        //
        try
        {
            item = (ToolboxItem)Activator.CreateInstance(toolType, true);
        }
        catch
        {
        }
    }

    return item;
}

GetToolboxItem method is from http://msdn.microsoft.com/en-us/library/aa480213.aspx source, in the ToolboxService class.

Cheers, Carlos

问题回答

This might sound stupid as my system is shutting down. :) But can you check your WorkflowView for whether AllowDrop is set? Have you handled the DragEnter event?





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签