Handling flicks on object - c#

I have created a new UIElement that derives from Systen.Windows.Controls.Canvas.
I am trying to handle flicks made on this object.
Everything is done in C#, in code (no XAML) using the Silverlight Phone Toolkit (February version as I want to target 7.0)
In my object constructor I do:
//Create gesture handling
gl = GestureService.GetGestureListener(this);
gl.Flick += new EventHandler<FlickGestureEventArgs>(gl_Flick);
and gl_Flick is simply:
void gl_Flick(object sender, FlickGestureEventArgs e)
{
if (e.HorizontalVelocity >= 0)
{
// Right swipe (flick)
if (gotSwipe != null)
{
gotSwipe(this, e);
}
}
}
Now, in the constructor, I also create and add a few TextBlocks
For some reason, the flick is only generating an event if done over one of those TextBocks. If I do the flick on any of the empty area of the Canvas nothing occurs.
As I can't find any documentations related to the Silverlight toolkit, everything has been done via trials&errors.
How could I do, so the flick will be recognised when performed anywhere over this canvas and not limited to over the children it contains?

I'm more focused towards WPF, but the way you talk about it reminds me of the classic null background issue.
The solution: set a non null background for your canvas.
EDIT: something like
myCanvas.Background = new SolidColorBrush(Color.FromArgb(1, 0, 0, 1));

Related

LayoutParams change only takes effect in fullscreen

im using Xamarin with MvvmCross.
Ive done a FragmentDialog with a recyclerView inside, the list is populated via bindings on xml file, so i have no adapter and i should keep it this way.
If im not wrong, theres no built in way to make the recyclerView take only the size needed for its content, this should not be a problem, but in this case i need the list to start from bottom...
So i did this (its a custom fullscreen dialog) :
MvxRecyclerView list = Dialog.FindViewById<MvxRecyclerView>(Resource.Id.recyclerview);
list.LayoutChange += List_LayoutChange;
Then in layoutChange
private void List_LayoutChange(object sender, View.LayoutChangeEventArgs e)
{
MvxRecyclerView list = Dialog.FindViewById<MvxRecyclerView>(Resource.Id.recyclerview);
int itemHeight = list.GetChildAt(0).Height;
if (itemHeight != 0)
{
ViewGroup.LayoutParams prms = list.LayoutParameters;
prms.Height = itemHeight * list.GetAdapter().ItemCount;
list.LayoutParameters = prms;
list.LayoutChange -= List_LayoutChange;
list.RequestLayout();
}
}
That was working fine, the list get exactly the height needed and the list looks like it starts from bottom.
Now the client tell me that he doesnt like the fullscreen dialog and wants the status bar, i think that should be easy, just to remove this line at the dialog creation right?
dialog.Window.AddFlags(WindowManagerFlags.Fullscreen);
But looks like its not that easy, when the dialog its not fullscreen the layoutParams change seems to have no effect, it just dont do nothing.
My method is being called and i get the right item height, it just dont change the recyclerview height.
Notice that setting fullscreen at creation and clearing the flag after the recyclerview params change works
So looks like it only works during fullscreen mode.
Can someone throw some light at this?
Thanks in advance.
As you said, RecyclerView was not aware of its size.
Since last update to the support lib, it is !
http://android-developers.blogspot.fr/2016/02/android-support-library-232.html
The RecyclerView widget provides an advanced and flexible base for creating lists and grids as well as supporting animations. This release brings an exciting new feature to the LayoutManager API: auto-measurement! This allows a RecyclerView to size itself based on the size of its contents. This means that previously unavailable scenarios, such as using WRAP_CONTENT for a dimension of the RecyclerView, are now possible. You’ll find all built in LayoutManagers now support auto-measurement.
I would suggest to wait for the Xamarin wrapped lib (there is already a beta https://www.nuget.org/packages/Xamarin.Android.Support.v4/23.2.0-beta1)

How can I do handwriting recognition each time a user has finished tracing a stroke?

Basing myself on the code given by MSDN for Handwriting Recognition in windows 10 apps, I tried to have it recognize the handwriting automatically after the user has finished tracing an ink stroke rather than when clicking a button.
I have been able to do something similar in a Windows 8.1 metro app by calling my handwriting recognition method when the PointerReleased event was triggered in my canvas. It worked great and I tried to emulate the same behavior in UWP.
The PointerReleased event was not firing in the UWP app so I used the InkCanvas.InkPresenter.StrokeInput.StrokeEnded event instead to call this method :
async void RecognizeAsync(InkStrokeInput input, PointerEventArgs e)
{
IReadOnlyList<InkStroke> currentStrokes =myInkCanvas.InkPresenter.StrokeContainer.GetStrokes();
if (currentStrokes.Count > 0)
{
var recognitionResults = await inkRecognizerContainer.RecognizeAsync(myInkCanvas.InkPresenter.StrokeContainer, InkRecognitionTarget.All);
if (recognitionResults.Count > 0)
{
// Display recognition result
string str = "Recognition result:";
foreach (var r in recognitionResults)
{
str += " " + r.GetTextCandidates()[0];
}
Status.Text=str;
}
else
{
Status.Text = "No text recognized.";
}
}
else
{
Status.Text="Must first write something.";
}
}
It's close to what I want to achieve, except the last stroke is not taken into account.
I guess that when the StrokeEnded event is triggered, the InkStroke has not yet been "processed" and thus it is not included in currentStrokes.
I tried to circumvent this problem by adding the Strokes corresponding to the InkStrokeInput of the event to the StrokeContainer I use as a parameter for the recognition :
InkStrokeContainer totalStrokes=new InkStrokeContainer();
if (currentStrokes.Count > 0) {
totalStrokes= myInkCanvas.InkPresenter.StrokeContainer;
}
totalStrokes.AddStrokes(input.InkPresenter.StrokeContainer.GetStrokes());
var recognitionResults = await inkRecognizerContainer.RecognizeAsync(totalStrokes, InkRecognitionTarget.All);
But input.InkPresenter.StrokeContainer.GetStrokes() returns an empty List.
Is there a way for me to access the current Stroke when the event is triggered ? Or is there another event I could use to call the handwriting recognition after the stroke has been "processed" ?
Or another way to automatically recognize the handwriting for all the current InkStrokes alltogether ?
I have found a way to achieve the result I was expecting by calling my RecognizedAsync method when the InkCanvas.InkPresenter.StrokesCollected event is triggered.
From the MSDN documentation :
InkPresenter.StrokesCollected event
Occurs when one or more ink strokes are processed ("wet" to "dry") by the >application thread.
By default, an ink stroke is processed on a low-latency background thread and >rendered wet as it is drawn. When the stroke is completed (pen or finger >lifted, or mouse button released), the stroke is processed on the UI thread >and rendered dry to the InkCanvas layer (above the application content).

WPF, non-overlapping windows [duplicate]

I have a multi-window application in WPF, where my main application window is invisible (Visibility=Collapsed) containing visible child windows. Application creates child windows on-demand. I need an algorithm to determine the coordinates and dimensions of the newly created child window. Obviously, the new child window should not cover (fully) another child window. Does WPF offer any support whatsoever to implement this kind of logic ? Or, do I have to do everything on my own. I imagine this would be a lot of work. The behavior I am looking for is very similar to Sticky Notes behavior in Windows 7.
Part of my code will help you to really understand what I mean:
public void ViewModelsCollectionChanged(object sender,
NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (ViewModel viewModel in e.NewItems)
{
View view = new View(viewModel);
view.Owner = SleekNoteUI.App.Current.MainWindow;
...
}
}
}

Kinect Custom Cursor

I need to make a cursor in Kinect, but I don't know where to start. I need to make it using WPF and C#. Cursor should be in shape of hand and when I hover over element the "loading" circle should appear, and when it "loads" it should fire click event on hovered element.
I'm sure that your're all familiar with this.
It would be of great help if someone could write me some directions oh how to accomplish this.
Here is a code snippet that might help you:
using Microsoft.Research.Kinect.Nui;
Runtime nui = Runtime.Kinects[0];
nui.Initialize(RuntimeOptions.UseSkeletalTracking);
nui.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(nui_SkeletonFrameReady);
void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
SkeletonFrame sf = e.SkeletonFrame;
SkeletonData d = (from s in sf.Skeletons
where s.TrackingState == SkeletonTrackingState.Tracked
select s).FirstOrDefault();
if (d != null)
{
SetHandPosition(imageCursor, d.Joints[JointID.HandLeft]);
}
}
void SetHandPosition(FrameworkElement e, Joint joint)
{
Joint scaledJoint = Coding4Fun.Kinect.Wpf.SkeletalExtensions.ScaleTo(joint, 600, 400, 0.75f, 0.75f);
Canvas.SetLeft(e, scaledJoint.Position.X);
Canvas.SetTop(e, scaledJoint.Position.Y);
}
If you want your cursor to be different hovering on an element then just go to the elements properties and set a cursor for that element. In Visual Studio you can choose a cursor in the elements properties.
To make a click on a hover over an element you have to implement the MouseEnter event
private void button1_MouseEnter(object sender, MouseEventArgs e)
{
....
}
Here are some infos about it:
button1.PerformClick() in wpf
Here is a nice solution using the official SDK, but even if you're not, it can be very (!) helpful (it was for me):
You should take a look at the (free) code available here Beginning Kinect Programming with the Microsoft Kinect SDK sample code you click on "Source Code/Downloads" and what's is going to interest you in the sample is the Chapter 6 (name of the folder).
Basically they're using a static class KinectInput that allow to raise new event like KinectCursorEnterEvent, there is a cursor manager KinectCursorManager which does almost everything get the hand position/update the cursor ... and They use an adorner to put the cursor, with the FrameworkElement you want as a cursor.
They implement the HoverButton you're talking about. It fires the click event after a timer elapsed (timer launched when the KinectCursorEnterEvent occured). The solution they propose is elegant, and allow an easy implementation of nice controls.
You can easily modify the code to handle the two cursor (that's the value-added of the Kinect, isn't it?)
having an Enumeration CursorSide:
public enum CursorSide
{
Left,
Right
}
and modifyong only the KinectCursorManager having a Dictionary of capacity 2, and the enumeration being the Key, and having a pointer on the elemtn under the cursor for each hand:
private Dictionary<CursorSide, CursorAdorner> _cursorAdorner;
private UIElement _lastElementOverRightHand;
private UIElement _lastElementOverLeftHand;
But before you have to remove the part of the code that does the selection of the primaryHand (basically the hand closest to the Kinect).
I hope this can help somebody :-]
The book is very interesting, you can buy it for a few bucks.

Design-Time drag and drop

I'm currently working of a project where my part is to design a Design Surface where the end user can add/remove/move controls at run-time.
I followed this tutorial "Hosting Windows Forms Designers, by Tim Dawson", and almost have implemented all the features I need.
Short story for those who don't want to read the tutorial : I implemented IDesignerHost, IContainer, ISelectionService, IToolboxService and some other interface, to create my design surface. I didn't use the System.ComponentModel.Design.DesignSurface already in the framework, mainly beacause I need a really custom design surface.
Question :
I want to allow user to drag & drop new Control from the IToolboxService to the IDesignerHost/IContainer. In this tutorial, you clic on a Control in the toolbox, the click on the design surface to add the control.
What i've found :
There is a built-in feature that
automagically does drag & drop from
IToolboxService to
System.ComponentModel.Design.DesignSurface but it is clearly not working if you implement IDesignerHost from nothing.
When you use the
Control.DoDragDrop(ToolboxItem)
method, to initiate a drag & drop :
IToolboxService.SerializeToolboxItem(ToolboxItem)
is called to serialize the item
IToolboxService.IsToolboxItem(object)
and
IToolboxService.IsSupported(object)
are called to evaluate if the
serialized ToolboxItem can be allowed
to be droped on the design surface
When you drop the control : IToolboxService.DeserializeToolboxItem(object serializedObject) is called by the design surface to deserialize the controldropped.
IToolboxService.SetCursor() is called to know if you define a custom cursor, or let the standard windows cursor.
Problem :
I implemented all mentionned above, in the "What i've found", but the drag & drop is buggy :
I drag, everything's fine, but when
hovering the design surface, my
cursor blink a little between
standard cursor and the
"DragDropEffects.Copy" style.
When I drop, nothing happens, and when my cursor leave the design surface (after I dropped), then the new Control is created and added where I dropped it.
Has anyone ever tried to do what I'm doing, and if so, how did you manage it ?
Is there anyone that has any pointer/link/good advices ?
Thank you =)
Is there anyone that has any
pointer/link/good advices?
Your issue seems to be addressed by the Microsoft Connect issue Mouse Events Consumed / Not Raised in 2.0 Designers. This issue is all but easy to grasp though, but apparently the upgrade from .NET Framework 1.1 (2003) to 2.0 (2006) implied a change in drag & drop behavior - given that the article you mentioned stems from 2003 this could well be related. Specifically you should scroll ahead to section Issue 2, citation:
You will now notice constant
flickering when dragging over the
form. This is partially caused by the
new drag-drop behavior in 2.0.
I'm unable to dig deeper into this right now myself but you might also be able to figure something from Customize Drag & Drop in the Designer, which addresses changed behavior regarding drag & drop between Visual Studio versions 2003 and 2005; quite likely this might be related and one of the accepted answers does in fact specifically reference the Microsoft Connect issue above, plus it offers more hints towards possible solutions too.
Me to worked on this questions for one day ago. This is my solution that found for my project like yours.
I drag, everything's fine, but when hovering the design surface, my cursor blink a little between standard cursor and the "DragDropEffects.Copy" style.
This is my toolboxservice.
class EasyAccordionToolboxService : AccordionControl, IToolboxService
{
EasyAccordionControlElement _SelectedElement;
public Control DesignPanel { get; set; }
public EasyAccordionToolboxService()
{
AddAccordions();
AllowItemSelection = true;
base.ElementClick += EasyAccordionToolboxService_ElementClick;
}
private void EasyAccordionToolboxService_ElementClick(object sender, ElementClickEventArgs e)
{
if (e.Element.Level == 1) this._SelectedElement = e.Element as EasyAccordionControlElement;
}
public ToolboxItem GetSelectedToolboxItem()
{
if(_SelectedElement != null)
{
var selectedToolboxItem = this._SelectedElement.ToolBoxItem;
this._SelectedElement = null;
return selectedToolboxItem;
}
else
{
return null;
}
}
public bool SetCursor()
{
if(this._SelectedElement == null)
{
this.DesignPanel.Cursor = Cursors.Default;
}
else
{
this.DesignPanel.Cursor = Cursors.Hand;
}
return true;
}
There are "DesignPanel" property and "SetCursor" methods. DesignPanel property is control referred to view of root designer.
When I drop, nothing happens, and when my cursor leave the design surface (after I dropped), then the new Control is created and added where I dropped it.
There is GetSelectedToolboxItem method in EasyAccordionToolBoxService implemented from IToolboxService. GetSelectedToolboxItem is your answer.
Finally,
designer = new EasyDesignSurface(propertyGrid);
var rootForm = (Form)designer.CreateComponent(typeof(Form));
rootForm.Name = "rootForm";
rootForm.Text = "BELGE";
rootForm.TopLevel = false;
rootForm.Size = new Size(600, 600);
designer.ComponentContainer.Add(rootForm);
var view = (Control)designer.View;
view.Dock = DockStyle.Fill;
designPanel.Controls.Add(view);
easyAccordionToolboxService1.DesignPanel = view;
designer.AddService(typeof(IToolboxService), easyAccordionToolboxService1);

Categories