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 desig开发者_高级运维ner.
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
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?
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
精彩评论