Helix Toolkit How to use MouseWheelEventHandler to run specific methods in other classes - mouseevent

I would like to run particular methods of a custom Camera class whenever the user zooms in or out in the helix toolkit view that my program is running inside of.
A key feature of this functionality is getting the mouseargs from the event so I can adjust the camera in a way that is proportional to the number of scroll ticks.
I began to try this:
public event PropertyChangedEventHandler PropertyChanged;
public virtual void onMouseWheeled(MouseDevice Mouse, int time,
MouseWheelEventArgs e) {
MouseWheel?.Invoke(this, new MouseWheelEventArgs(Mouse, time,
e.Delta)); }
//This next line goes in a MainWindow_Loaded method that gets called in the
//MainWindowConstructor
void MainWindow_Loaded(object sender, RoutedEventArgs e) {
view1.MouseWheel += new MouseWheelEventHandler(onMouseWheeled(Cursor,
Time.simTime, view1.MouseWheeledEventArgs)); }
but was having a lot of trouble figuring out how to pass a MouseWheelEventArgs object into the onMouseWheeled method when I'm trying to add the onMouseWheeled method to the MouseWheelEventHandler. Assuming nothing is fundamentally wrong with that sentence, which is nothing more than wishful thinking, The last thing I am trying to figure out is how to get mouse wheel event args so that I can pass it into a method.
Then I tried this:
public event MouseWheelEventHandler MouseWheel;
public virtual void onMouseWheeled(object sender, MouseWheelEventArgs e)
{
Console.WriteLine(e.Delta);
}
//In Main Window Loaded method...
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
view1.MouseWheel += onMouseWheeled;
}
But I get no output when i scroll the wheel. I assumed this might actually work because view1 is the helix window I'm attaching all of my objects to, as children of view1.
Basically my main questions are:
What does invoke actually do? I only have this running to try to see if its working because onPropertyChanged methods I always use run the Invoke command like so. I'm actually not sure where I'm going with this.
How does the handler work?
How do the event args get called out so that I can use them and pass them as objects to other methods?
Thank you for your time. And Thank you twice for any and all pointers and advice you may give me.

Try to use preview mouse wheel event

Related

Animation not starting until UI updates or touch event

I have a strange problem with an AlphaAnimation. It is supposed to run repeatedly when an AsyncTask handler is called.
However, the first time the handler is called in the Activity, the animation won't start unless I touch the screen or if the UI is updated (by pressing the phone's menu button for example).
The strange part is that once the animation has run at least once, it will start without problem if the handler is called again.
Here's what the code looks like:
// AsyncTask handler
public void onNetworkEvent()
{
this.runOnUiThread(new Runnable() {
#Override
public void run()
{
flashScreen(Animation.INFINITE);
}
});
}
// Called method
private void flashScreen(int repeatCount)
{
final View flashView = this.findViewById(R.id.mainMenuFlashView);
AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
alphaAnimation.setRepeatCount(repeatCount);
alphaAnimation.setRepeatMode(Animation.RESTART);
alphaAnimation.setDuration(300);
alphaAnimation.setInterpolator(new DecelerateInterpolator());
alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation)
{
flashView.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationEnd(Animation animation)
{
flashView.setVisibility(View.GONE);
}
#Override
public void onAnimationRepeat(Animation animation) { }
});
flashView.startAnimation(alphaAnimation);
}
I have noticed that runOnUIThread isn't necessary (same results occur if I don't use it), but I prefer keeping it as I'm not on the UI thread.
Any ideas on what could cause this?
A little more research showed that my problem was the same a this question:
Layout animation not working on first run
The flashView's visibility was set to GONE by default (causing the Animation not to start immediately as the View had never been rendered), so I just need to set it to INVISIBLE before calling flashView.startAnimation()
If setting the View to VISIBLE won't work, as was in my case, it helped for me to call requestLayout() before starting the Animation, like so:
Animation an = new Animation() {
...
view.requestLayout();
view.startAnimation(an);
In my case, my View was 0dip high which prevented onAnimationStart from being called, this helped me around that problem.
This worked for me:
view.setVisibility(View.VISIBLE);
view.startAnimation(animation);
I had to set the view to VISIBLE (not INVISIBLE, neither GONE), causing the view renderization needed to animate it.
That's not an easy one. Till you got a real answer : The animation start is triggered by onNetworkEvent. As we don't know the rest of the code, you should look there, try to change onNetworkEvent by an other event that you can easily identify, just to debug if the rest of the code is ok or if it's just the trigger that is responsible for it.
May be it will help someone, because previous answers not helped me.
My animation was changing height of view (from 0 to it's real height and back) on click - expand and collapse animations.
Nothing worked until i added listener and set visibility to GONE, when animation ends:
collapseAnim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
view.setVisibility(View.GONE);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
And when expand just set it to VISIBLE before animation:
view.setVisibility(View.VISIBLE);
view.startAnimation(expandAnim);

Number of Touchpoints in GestureRecognizer

I am using the GestureRecognizer to detect drag and pinch gestures.
The ManipulationStarted, ManipulationUpdated and ManipulationCompleted events provide the translation and scale values that are needed to pinch and drag.
However I cant figure out how to distinguish between drag (1 touch point) and pinch (2 touch points) gestures. There is no information about the number of touchpoints in GestureRecognizer.
How can I distinguish between drag and pinch with the GestureRecognizer?
Well, I feel it is very hacky (as most solutions seem to be for a useable WinRT app) but you can create a List<uint> to keep track of the number of pointers that are currently down on the screen. You would have to handle the PointerPressed event on whatever control you are interacting with (Let's say you are using a Canvas) to "capture" the pointers as they are pressed. That is where you would populate the List<uint>. Don't forget to clear the list at the end of the ManipulationCompleted event as well as any event that would fire upon the end of any gestures (like PointerReleased, PointerCanceled, and PointerCaptureLost). Maybe it would be a good idea to make sure the list is cleared in the ManipulationStarted event. Perhaps you can try that and see how that works for you.
In the ManipulationCompleted event, you can check if your List contains exactly 2 elements (PointerIds). If so, then you know it is a pinch/zoom.
Here is what it could look like:
private void Canvas_PointerPressed(object sender, PointerRoutedEventArgs e)
{
var ps = e.GetIntermediatePoints(null);
if (ps != null && ps.Count > 0)
{
this.gestureRecognizer.ProcessDownEvent(ps[0]);
this.pointerList.Add(e.Pointer.PointerId);
e.Handled = true;
}
}
private void gestureRecognizer_ManipulationCompleted(GestureRecognizer sender, ManipulationCompletedEventArgs args)
{
if (this.pointerList.Count == 2)
{
// This could be your pinch or zoom.
}
else
{
// This could be your drag.
}
// Don't forget to clear the list.
this.pointerList.Clear();
}
// Make sure you clear your list in whatever events make sense.
private void Canvas_PointerReleased(object sender, PointerRoutedEventArgs e)
{
this.pointerList.Clear();
}
private void Canvas_PointerCanceled(object sender, PointerRoutedEventArgs e)
{
this.pointerList.Clear();
}
I have been struggling with the same question for a few hours now and it looks WinRT platform does not provide that. What it instead provides is Delta.Rotation and Delta.Scale values in addition to Delta.Translation with the arguments to ManipulationUpdated callback.
If Delta.Rotation is 0 (or very close to zero - because it is a float value) and Delta.Scale is 1 (or very close to 1), you can conclude that a pinch operation is not the case and a drag operation is being carried otherwise it is a pinch operation. It is not the best you can get but it looks it is the only availability for the time being.

How to execute a binding for a metro control

I want to write the contents of a per occasion active TextBox back to the bound property of the ViewModel when the user presses the key combination for save (Ctrl-S).
My Problem with it is, that I'm not able to trigger the execution of the binding so that the bound Text-Property reflects the contents of the TextBox.
-There seems to be no GetBinding-method. Therefore I can not get the Binding and execute it manualy.
-There is no Validate-method such as in WinForms which executes the Binding
-Giving focus to another control from within KeyDown seems not to work, the binding does not execute
How can I achieve this?
Take a look at Aaron's discussion about this in his WiredPrarie blog post : http://www.wiredprairie.us/blog/index.php/archives/1701
I think I understand your question better now. One way around this would be to use a sub-classed textbox with a new property like this from here:
public class BindableTextBox : TextBox
{
public string BindableText
{
get { return (string)GetValue(BindableTextProperty); }
set { SetValue(BindableTextProperty, value); }
}
// Using a DependencyProperty as the backing store for BindableText. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BindableTextProperty =
DependencyProperty.Register("BindableText", typeof(string), typeof(BindableTextBox), new PropertyMetadata("", OnBindableTextChanged));
private static void OnBindableTextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs eventArgs)
{
((BindableTextBox)sender).OnBindableTextChanged((string)eventArgs.OldValue, (string)eventArgs.NewValue);
}
public BindableTextBox()
{
TextChanged += BindableTextBox_TextChanged;
}
private void OnBindableTextChanged(string oldValue, string newValue)
{
Text = newValue ? ? string.Empty; // null is not allowed as value!
}
private void BindableTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
BindableText = Text;
}
}
Then bind to the BindableText property.
Solution for command-instances
Here a solution I have found which is relatively leightweight, but also a bit "hackish":
btn.Focus(Windows.UI.Xaml.FocusState.Programmatic);
Dispatcher.ProcessEvent(CoreProcessEventsOption.ProcessAllIfPresent);
btn.Command.Execute(null);
First I give the focus to another control (In my case the button which has the bound command). Then I give the system time to execute the bindings and in the end I raise the command which is bound to the button.
Solution without bound commands
Give the Focus to another control and call the Dispatcher.ProcessEvent(...).
anotherControl.Focus(Windows.UI.Xaml.FocusState.Programmatic);
Dispatcher.ProcessEvent(CoreProcessEventsOption.ProcessAllIfPresent);
// Do your action here, the bound Text-property (or every other bound property) is now ready, binding has been executed
Please see also the solution of BStateham.
It's another way to solve the problem

nhibernate, async loading

I have a question about hibernate. I use different controls in my application (treeview, combobox, ...). I get the content for these controls through nhibernate. The problem is, that it takes a lot of time to get the data. Drung this time the form is frozen.
I want to load the data in another thread. But i don't know where to put that thread. I'm new at hibernate, maybe you have more experience about that.
This isn't really an NHibernate problem, but rather a .NET Windows Forms threading one. Anyways, on a Forms environment, the easiest way to load all the NHibernate on a background thread would be to use the BackgroundWorker component.
private void LoadData(object sender, EventArgs e)
{
// This event fires whatever's in DoWork() on a separate thread.
backgroundWorker1.RunWorkerAsync();
// Things to do asynchronous operation.
timer1.Start();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// NHibernate loading goes here...
var employees = Session.CreateCriteria<Employee>();
combobox1.DataSource = employees;
}

Removing all event handlers in one go

Problem: I have a document class which contains a list of objects. These objects raise events such as SolutionExpired, DisplayExpired etc. The document needs to respond to this.
Documents can sometimes exchange objects, but a single object should never be 'part' of more than one document.
My document class contains a bunch of methods which serve as event handlers. Whenever an object enters the document, I use AddHandler to set up the events, and whenever an object is removed from the document I use RemoveHandler to undo the damage. However, there are cases where it's difficult to make sure all the steps are properly taken and I might thus end up with rogue event handlers.
Long story short; how do I remove all the handlers that are pointing to a specific method? Note, I don't have a list of potential event sources, these could be stored anywhere.
Something like:
RemoveHandler *.SolutionExpired, AddressOf DefObj_SolutionExpired
You can use Delegate.RemoveAll(). (The part you're interested in is in button2_Click)
public void Form_Load(object sender, EventArgs e)
{
button1.Click += new EventHandler(button1_Click);
button1.Click += new EventHandler(button1_Click);
button2.Click += new EventHandler(button2_Click);
TestEvent += new EventHandler(Form_TestEvent);
}
event EventHandler TestEvent;
void OnTestEvent(EventArgs e)
{
if (TestEvent != null)
TestEvent(this, e);
}
void Form_TestEvent(object sender, EventArgs e)
{
MessageBox.Show("TestEvent fired");
}
void button2_Click(object sender, EventArgs e)
{
Delegate d = TestEvent as Delegate;
TestEvent = Delegate.RemoveAll(d, d) as EventHandler;
}
void button1_Click(object sender, EventArgs e)
{
OnTestEvent(EventArgs.Empty);
}
You should note that it doesn't alter the contents of the delegates you pass in to it, it returns an altered delegate. Consequently, you won't be able to alter the events on a button you've dropped on a form from the form, as button1.Click can only have += or -= used on it, not =. This won't compile:
button1.Click = Delegate.RemoveAll(d, d) as EventHandler;
Also, be sure that wherever you're implementing this you're watching out for the potential of race conditions. You could end up with some really strange behavior if you're removing handlers from an event that is being called by another thread!
public class TheAnswer
{
public event EventHandler MyEvent = delegate { };
public void RemoveFromMyEvent(string methodName)
{
foreach (var handler in MyEvent.GetInvocationList())
{
if (handler.Method.Name == methodName)
{
MyEvent -= (EventHandler)handler;
}
}
}
}
EDIT 2: Apologies for my misunderstanding--I see that you were pretty clear about not having access to the event sources in your original post.
The simplest way I can think of to solve this problem involves implementing a Shared dictionary of object-to-document bindings. When an object enters a document, check the dictionary for an existing binding to another document; if present, remove handlers that refer to the old document before adding them for the new. Either way, update the dictionary with the new binding.
I think in most cases the performance and memory impacts would be negligible: unless you're dealing with many tens of thousands of small objects and frequently exchange them between documents, the memory overhead of each key/value pair and performance hit for each lookup operation should be fairly small.
As an alternative: if you can detect (in the document event handlers) that the sender of the event is no longer relevant to the document, you can detach the events there.
These seem like the kind of ideas you might have already rejected--but maybe not!
Use Delegate.RemoveAll (maybe using reflection if the Delegate instance is private).