Drag a custom activity in a re-hosted workflow designer - wpf

Hello
I have a problem in my Design which is in this http://archive.msdn.microsoft.com/wfxbap/Release/ProjectReleases.aspx?ReleaseId=4668
I have made a custom activity in my Re-hosted workflow designer in WPF, and I make this custom activity shows in the end-user toolbar with the other activites, but the custom one can't be drop into the sequence at all like other activities.
I put the AllowDrop="True" in the .XAML file and the following in the .cs file:
protected override void OnDragEnter(DragEventArgs e)
{
//Check the object is actually something we want to be droppable
if (DragDropHelper.AllowDrop(
e.Data,
this.Context,
typeof(Activity)))
{
e.Effects = (DragDropEffects.Move & e.AllowedEffects);
e.Handled = true;
}
base.OnDragEnter(e);
}
protected override void OnDragOver(DragEventArgs e)
{
//Check the object is actually something we want to be droppable
if (DragDropHelper.AllowDrop(
e.Data,
this.Context,
typeof(Activity)))
{
e.Effects = (DragDropEffects.Move & e.AllowedEffects);
e.Handled = true;
}
base.OnDragOver(e);
}
protected override void OnDrop(DragEventArgs e)
{
//droppedItem - may be a ModelItem or a newly instantiated object (from toolbox)
object droppedItem = DragDropHelper.GetDroppedObject(this, e, this.Context);
ModelItem canvasActivity = this.ModelItem;
canvasActivity.Properties["Children"].Collection.Add(droppedItem);
e.Handled = true;
DragDropHelper.SetDragDropCompletedEffects(e, DragDropEffects.Move);
base.OnDrop(e);
}
Any help please?

I realize this post is old but I just ran across this problem as well so thought I would post for anyone else who stumbles upon this. I found that adding your custom Activity library to the same binary path as your rehosted designer should do the trick.

Related

Integration Testing of WPF GUI: How do I identify that current work was finished

I want to run integration UI tests on my WPF application, and I'm not sure how to detect when the current test has finished so that I can proceed to the next one.
Simplifying, suppose I have a button on my window. When the button is clicked I disable it, I modify the model, and I re-enable the button. Once it detects that the model has changed, WPF changes the view on the screen.
Now I want to run a test that simulates clicking the button again and again. To click the button I’ll use automation, as described in this SO question. But how do I know when the work is finished and the display updated, so as to "click" the button again? Do I hook the botton’s IsEnabledChanged, or is there some global indication that the current cycle of processing has finished?
Edit: What was missing in my description is that I want the user to see the interim results on the screen. For example, if the test has 10 phases I want the user to see something like a Step Counter label with values 1 .. 10 appearing on the screen, and not just the number changing immediately from 1 to 10. See my answer below.
how do I know when the work is finished and the display updated, so as to "click" the button again?
According to your description, you said When the button is clicked I disable it, I modify the model, and I re-enable the button.
Therefore, I can only assume that when the model has changed, the Button will be re-enabled. So you could either attach a handler to the model's NotifyPropertyChanged event, or as you suggested, add a handler for the IsEnabledChanged event.
Here is how I managed to get it working. This might be trivial - I'm a novice with GUI. I'm just posting it here in the hope it'll help other novices like me :)
Anyhow, what I used is a two button solutions: Test and Step. Test starts the testing sequence, Step runs each step of the tests. The Step buttons interact with an Integration Tester By Steps helper.
The helper receives an Init with the Number Of Commands as parameter, (currently the helper generates random commands by itself, so it just needs to know how many commands to generate). The helpe provides a Step method to execute the next command, and a Needs More Steps property to indicate whether testing should continue.
The helper derives form INotifyPropertyChanged and has a Counter dependency property that is displayed on the main window.
The states of the Test and Step buttons are controlled by three helper methods: SetButtonsFor_OutsideTesting, SetButtonsFor_InsideTestingOutsideAnyStep and SetButtonsFor_InsideTestingInsideAStep.
First, I verified that everything is working manually, and then I added a timer and automated the process using the Stack Overflow suggestions on how to programmatically click a button in WPF and how to make a WPF Timer Like C# Timer.
Now, here's the Main Window's code:
private void Test_Click(object sender, RoutedEventArgs e)
{
SetButtonsFor_InsideTestingOutsideAnyStep();
RunTheTestBySteps();
}
public readonly IntegrationTesterBySteps _integrationTesterBySteps =
new IntegrationTesterBySteps();
void RunTheTestBySteps()
{
SetButtonsFor_InsideTestingOutsideAnyStep();
IntegrationTesterBySteps.Init(10);
StartTheTimer();
}
private void StartTheTimer()
{
DispatcherTimer = new DispatcherTimer();
DispatcherTimer.Tick += DispatcherTimer_Tick;
DispatcherTimer.Interval = new TimeSpan(0, 0, 1);
DispatcherTimer.Start();
}
private void StopTheTimer()
{
DispatcherTimer.Stop();
DispatcherTimer.Tick -= DispatcherTimer_Tick;
}
private DispatcherTimer DispatcherTimer { get; set; }
private void DispatcherTimer_Tick(object sender, EventArgs e)
{
if (!BtnStep.IsEnabled) return;
ClickTheStepButton();
CommandManager.InvalidateRequerySuggested();
}
private void BtnStep_Click(object sender, RoutedEventArgs e)
{
SetButtonsFor_InsideTestingInsideAStep();
IntegrationTesterBySteps.Step();
if (this.IntegrationTesterBySteps.NeedsMoreSteps)
SetButtonsFor_InsideTestingOutsideAnyStep();
else
{
SetButtonsFor_OutsideTesting();
StopTheTimer();
}
}
private void ClickTheStepButton()
{
var peer = new ButtonAutomationPeer(BtnStep);
var invokeProv = peer.GetPattern(PatternInterface.Invoke)
as IInvokeProvider;
if (invokeProv != null)
invokeProv.Invoke();
}
void SetButtonsFor_InsideTestingInsideAStep()
{
BtnTest.IsEnabled = false;
BtnStep.IsEnabled = false;
}
void SetButtonsFor_InsideTestingOutsideAnyStep()
{
BtnTest.IsEnabled = false;
BtnStep.IsEnabled = true;
}
void SetButtonsFor_OutsideTesting()
{
BtnTest.IsEnabled = true;
BtnStep.IsEnabled = false;
}

throwing out touches in WPF

I'm trying to eliminate TouchDevices in a WPF for Surface so I can ignore non-finger touches because blobs seem to trigger events I don't want.
At first I had something simple like this
private void SurfaceWindow1_PreviewTouchDown(object sender, TouchEventArgs e)
{
if (!e.TouchDevice.GetIsFingerRecognized() && InteractiveSurface.PrimarySurfaceDevice.IsFingerRecognitionSupported == true)
{
e.Handled = true;
}
}
Which works well to stop touch interactions with things like inside ScatterViewItems and manipulations. however there must be something else that happens before PreviewTouchDown because I can use a blob to activate an SVI and bring it to the top although no other manipulations occur. I'm guessin TouchEnter on the SVI still shows up and brings it forward but handling TouchEnter on all the elements gives me the same thing so there's still something else going on.
I looked into Touch.FrameReported but I can't release the proper TouchCaptures before the SVIs hear about it
private void myTouchFrameHandler(object sender, TouchFrameEventArgs e)
{
foreach (TouchPoint _tp in e.GetTouchPoints(this)) {
if (!_tp.TouchDevice.GetIsFingerRecognized())
{
this.ReleaseAllTouchCaptures();
}
}
}
Any ideas?
Thanks
I stumbled upon the same problem and implemented an attached behavior for ScatterViewItems. This behavior disables the automatic IsTopmostOnActivation behavior and listens to PreviewTouchDown events to decide if an item is to be brought to top based on a test condition. It features an easy to use activation method
CustomTopmostBehavior.Activate();
which adds an application-wide style enabling the behavior for all ScatterViewItems.
The behavior can be customized by setting its TestCondition property which is by default:
CustomTopmostBehavior.TestCondition = (t) =>
{
return t.GetIsFingerRecognized();
};
Ok here's my dirty workaround to stop Touches from advancing when they're not recognized as fingers, and stopping SVIs from rising to the top when hovered over.
this.PreviewTouchDown += new EventHandler<System.Windows.Input.TouchEventArgs>(SurfaceWindow1_PreviewTouchDown);
SVI.TouchEnter += new EventHandler<TouchEventArgs>(SVI_TouchEnter);
SVI.TouchLeave +=new EventHandler<TouchEventArgs>(SVI_TouchLeave);
void SurfaceWindow1_PreviewTouchDown(object sender, System.Windows.Input.TouchEventArgs e)
{
if (!e.TouchDevice.GetIsFingerRecognized() && Microsoft.Surface.Presentation.Input.InteractiveSurface.PrimarySurfaceDevice.IsFingerRecognitionSupported) { e.Handled = true; }
else
{
//normal stuff
}
}
private void SVI_TouchEnter(object sender, TouchEventArgs e)
{
ScatterViewItem svi = sender as ScatterViewItem;
if (!e.TouchDevice.GetIsFingerRecognized() && Microsoft.Surface.Presentation.Input.InteractiveSurface.PrimarySurfaceDevice.IsFingerRecognitionSupported == true)
{
svi.IsTopmostOnActivation = false;
e.Handled = true;
}
else
{
foreach(ScatterViewItem svi in mainScatterView.Items.SourceCollection){
svi.IsTopmostOnActivation = false;
}
SVI.IsTopmostOnActivation = true;
}
}
private void SVI_TouchLeave(object sender, TouchEventArgs e)
{
ScatterViewItem svi = sender as ScatterViewItem;
svi.IsTopmostOnActivation = true;
}
I feel gross just coming up with such an unclever method. But since there's no tunneling TouchEnter, you would have to check all the visual tree objects that get a TouchEnter, which would even worse. Plus I just couldn't figure out how to use the protected method TouchDevice.Deactivate() anyway. But since the SVIs capture the touchDevice anyway and get restacked the only way I found to keep them in place is with the TopmostOnActivation Property, then catch the PreviewTouchDown on the Window and throw out non-fingers.
There's got to be a better way to get into the touch hierarchy, right?
OK so I've dug deeper into the touch hierarchy.
First of all TouchEnter happens before all the TouchDowns occur, but there's no tunneling event for that. TouchFrameHandler occurs after all the events are done, so throw that out.
Then I realized Releasing Captures on UIElements doesn't really make a difference for my problem because the Touch is already Captured. So I need to eliminate the TouchDevice in TouchEnter on every element. There is a Deactivate method in TouchDevice but it's protected. If I can figure out how to Deactivate a TouchDevice I think that should do the trick. Does that sound reasonable? If so I have to figure out how to override a protected method.

WPF Creating a Command Library

New to WPF/XAML and looking to build a Command library for my application. Current version of my application is "flat" meaning all the code behind resides in my MainWindow.cs file. I've decided to separate things out into User Controls and all the UI part so far works great but....
I'm having trouble binding my commands to things now that I've done this. To make it simple I created a new WPF project, added my Menu control (Controls\Menu.xaml) and referenced this in my MainWindow.xaml. Now, I've gone ahead and added a CommandLibrary class and can't seem to get anything working. Here is my File -> New command code:
public static class MyAppCommands
{
private static RoutedUICommand _NewItem;
static MyAppCommands()
{
_NewItem = new RoutedUICommand("Create a new project", "NewItem", typeof(MyAppCommands));
}
public static RoutedUICommand NewItem
{
get { return _NewItem; }
}
private string filePath = null;
private bool dataChanged = false;
public static void NewItem_Executed(object sender, ExecutedRoutedEventArgs e)
{
if (dataChanged)
{
string sf = SaveFirst();
if (sf != "Cancel")
{
ClearState();
}
}
else
{
ClearState();
}
}
public static void NewItem_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
public static void BindCommandsToWindow(Window window)
{
window.CommandBindings.Add(new CommandBinding(NewItem, NewItem_Executed, NewItem_CanExecute));
}
Where do I put the below in my class as a lot of my command will be using them...?
private string filePath = null;
private bool dataChanged = false;
Many Thanks!
I think you could benefit from setting up some design patterns like MVC or MVVM.
Check out these frameworks:
Caliburn (my favorite)
Prism
You can also follow MVC or MVVM just using a couple small helper classes, check out ariticles around the web, like this one MVVM.
Check this if you want a light-weight framework: MVVM Foundation

Identify that a Window is completely hidden

In order to create a screen shot, I am hiding a wpf window. The code looks like that.
Hide();
var fullScreenshot = _cropper.TakeFullScreenshot();
Show();
Sometimes the Application is not hidden when the screen shot is taken. How can I can I identify, that the window is completely hidden?
I don't know how the screenshot is taken but I suspect that the UI-Thread has not removed all the content and therefore the TakeFullScreenshot sees rests of your app.
I would try to wait until your app has done all necessary ui-work and then trigger the TakeFullScreenshot-operation.
Trigger the ScreenShot-Operation with the Dispatcher:
Hide();
Dispatcher.BeginInvoke(new Action(delegate {
fullScreenshot = _cropper.TakeFullScreenshot();
Show();
}), System.Windows.Threading.DispatcherPriority.ContextIdle, null);
Currently I am trying out this solution:
public void Foo()
{
IsVisibleChanged += WhenVisibiltyChangend_TakeScreenshot_and_OpenCreateTicketDialog;
Hide();
}}
void WhenVisibiltyChangend(object sender, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue == false) {
var fullScreenshot = _cropper.TakeFullScreenshot();
Show();
}
}
I hope this is the correct answer, but I have to do some additional tests.

Silverlight 3 Out of the Browser Updates

I have a few users that are using a silverlight app that aren't recieving updates when a new release is published. Isn't this suppose to be automatic or perhaps I'm missing an option somewhere? I was also starting to think that maybe the XAP file is cached and I some how need to prevent that.
Any thoughts out there?
You need to write a few lines of code.
If you're familiar with 'one click' deployment then some of the options you're used to don't exist in Silverlight. You need to write the code yourself.
http://nerddawg.blogspot.com/2009/07/silverlight-out-of-browser-apps-how.html
private void Application_Startup(object sender, StartupEventArgs e)
{
this.RootVisual = new MainPage();
if (Application.Current.IsRunningOutOfBrowser)
{
Application.Current.CheckAndDownloadUpdateAsync();
}
and then in your App() constructor :
Application.Current.CheckAndDownloadUpdateCompleted +=
new CheckAndDownloadUpdateCompletedEventHandler(Current_CheckAndDownloadUpdateCompleted);
and an event handler :
void Current_CheckAndDownloadUpdateCompleted(object sender, CheckAndDownloadUpdateCompletedEventArgs e)
{
// http://nerddawg.blogspot.com/2009/07/silverlight-out-of-browser-apps-how.html
if (e.UpdateAvailable)
{
MessageBox.Show("The application has been updated! Please close and reopen it to load the new version.");
}
else if (e.Error != null && e.Error is PlatformNotSupportedException)
{
MessageBox.Show("An application update is available, " +
"but it requires a new version of Silverlight. " +
"Please contact tech support for further instructions.");
}
}
It only auto updates if the developer performs the CheckAndDownloadUpdateAsync() call. See updates: http://timheuer.com/blog/archive/2009/07/10/silverlight-3-released-what-is-new-and-changed.aspx#oob

Resources