C# Träge Touch-App für Windows 8

Krik

Fleet Admiral
Registriert
Juni 2005
Beiträge
11.994
Moin,

ich programmiere gerade an einem kleinen Programm, bei dem man per Touch-Drag'n'Drop ListViewItems von einer ListView in eine andere schieben soll.

Die ListViews sind so definiert:
Code:
<ListView x:Name="DragList" SelectionMode="Single" MouseMove="DragList_MouseMove" TouchMove="DragList_TouchMove" />

<ListView x:Name="DropList" SelectionMode="Single" AllowDrop="True" Drop="DropList_Drop" DragEnter="DropList_DragEnter" DragLeave="DropList_DragLeave" />
Die DragList wird mit diesen Daten gefüttert:
Code:
DragList.ItemsSource = new ObservableCollection<ListViewItem>()
{
    new ListViewItem() { Content = "Element 1", FontSize = 14, Height = 40, BorderThickness = new Thickness(2), BorderBrush = Brushes.Black, HorizontalContentAlignment = HorizontalAlignment.Center, Margin = new Thickness(5) },
    new ListViewItem() { Content = "Element 2", FontSize = 20, Height = 55, BorderThickness = new Thickness(2), BorderBrush = Brushes.Black, HorizontalContentAlignment = HorizontalAlignment.Center, Margin = new Thickness(5) },
    new ListViewItem() { Content = "Element 3", FontSize = 25, Height = 70, BorderThickness = new Thickness(2), BorderBrush = Brushes.Black, HorizontalContentAlignment = HorizontalAlignment.Center, Margin = new Thickness(5) },
    new ListViewItem() { Content = "Element 4", FontSize = 31, Height = 85, BorderThickness = new Thickness(2), BorderBrush = Brushes.Black, HorizontalContentAlignment = HorizontalAlignment.Center, Margin = new Thickness(5) },
    new ListViewItem() { Content = "Element 5", FontSize = 36, Height = 100, BorderThickness = new Thickness(2), BorderBrush = Brushes.Black, HorizontalContentAlignment = HorizontalAlignment.Center, Margin = new Thickness(5) }
};

Die Drag'n'Drop-Events für die Touch-Eingabe sehen so aus:
Code:
private void DragList_TouchMove(object sender, TouchEventArgs e)
{
    if (sender != null && e.GetTouchPoint(DragList) != null && e.GetTouchPoint(DragList).Action == TouchAction.Move && DragList.SelectedItem != null)
    {
        DragDrop.DoDragDrop(DragList, DragList.SelectedItem, DragDropEffects.Move);
    }
}

private void DropList_Drop(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(typeof(ListViewItem)))
    {
        ListViewItem item = (ListViewItem)e.Data.GetData(typeof(ListViewItem));
        DropList.Items.Add(item);
        DropList.BorderBrush = Brushes.Black;

        DragList.SelectedItem = null; // Workaround für Programmcrash
        DropList.SelectedItem = null;

        e.Handled = true;
    }
}

private void DropList_DragEnter(object sender, DragEventArgs e)
{
    DropList.BorderBrush = Brushes.Red;
}

private void DropList_DragLeave(object sender, DragEventArgs e)
{
    DropList.BorderBrush = Brushes.Black;
}
Soweit ist alles i. O.

In der Praxis sieht es dann aber aber so aus, dass der Prozess auf einem kleinen DualCore-Tablet 37% Prozessorlast erzeugt und die Anwendung extrem langsam reagiert. Das geht so weit, dass man Sekunden auf eine Reaktion warten muss.
Die Verlangsamung beginnt, sobald man in der DragList das ausgewählte Item ändert, also auf ein anderes "touched."

Es muss etwas mit dem Drag'n'Drop oder dem Code drumherum zu tun haben, da ich ausschließlich hier das Problem habe. Mit Maus-Drag'n'Drop läuft übrigens alles einwandfrei und schnell.

Erkennt jemand vielleicht den Grund für die Verlangsamung oder hat eine Vermutung, woher das Problem kommt?


Gruß, Laurin



Edit:
Es ist noch ein zweites Problem aufgetaucht, das eventuell mit diesem hier zusammenhängt.
Ein Item wird in der DragList nicht richtig ausgewählt (kann man nicht per SelectedItem-Property holen), wenn man einfach nur den Finger drauf hält und rüberzieht. Man muss zwangsweise das Item antippen und den Finger wieder vom Bildschirm nehmen, bevor man dann "anfassen" und rüberziehen kann.

Tippt man das Item nicht an, ist es mit einem hellblauen Rahmen markiert. Tippt man es an, ist es mit einem Rahmen in einem dunkleren Blau markiert. Ich tippe deswegen darauf, dass hier irgendwie die Events nicht richtig geroutet werden (aber warum? ich greife doch nicht sonderlich groß ein).
 
Zuletzt bearbeitet:
Hallo!

Ich habe jetzt zwar noch kein Drag&Drop für Windows 8 programmiert, allerdings kann ich dir vielleicht bei deinem zweiten Problem helfen:
Das Problem ist, dass du zuerst das UIElement (ListView) brauchst, bevor du etwas verschieben kannst.
Dazu habe ich irgendwo im Internet mal folgendes gefunden:

Code:
private static object GetItemFromPoint(ListView view, Point point)
{
	UIElement element = view.InputHitTest(point) as UIElement;
	while (element != null)
	{
		if (element == view) { return null; }

		object item = view.ItemContainerGenerator.ItemFromContainer(element);
		bool itemFound = !ReferenceEquals(item, DependencyProperty.UnsetValue);
		if (itemFound) { return item; }
		element = VisualTreeHelper.GetParent(element) as UIElement;
	}
	return null;
}
Dies verwendest du in TouchMove ungefähr so:
Code:
	object obj = GetItemFromPoint((ListView)sender, e.GetPosition((ListView)sender));
Und überprüfst nicht nach SelectedItem != null sondern mit obj != null.

Hoffe, dass hilft dir weiter.
 
Großes Dankeschön! :)

Über den Code bin auch gestolpert, ich bin aber davon ausgegangen, dass erst ein SelectionChanged-Event gefeuert wird, bevor mein Drag'n'Drop ins Spiel kommt. Dass das nicht unbedingt der Fall sein muss, ist mir erst durch deinen Post klar geworden.

Ich habe das mal so eingebaut und es funktioniert perfekt. :daumen:



Nachtrag:
Das träge Programmverhalten tritt wirklich nur dann auf, wenn der User die Auswahl in der DragList ändert. Das Programm wird aber sofort wieder reaktionsfreudig, sobald man einfach mal ein Item drag'm'dropped.
Ich raff das nicht. Da muss ein Bug im .Net-Framework vorliegen - vermutlich an einer Stelle, wo er das SelectionChanged-Event in Verbindung mit Touch-Eingaben verarbeitet.
 
Zuletzt bearbeitet:
Ja bitte, kein Problem.

Ich habe bis jetzt Drag&Drop nur für Maus und in .NET3.5 gemacht. Dort hat es eigentlich immer hingehaut. Zwar kann ich nicht sagen, dass es extrem flott war, aber es hat nicht geruckelt.

Hast du in der ListView ein SelectionChanged Event abonniert? Oder ein MouseMove?
Vielleicht braucht dort etwas, etwas länger. Oder es verträgt sich nicht, wenn man beide aktiviert hat. Soweit ich weiß unterstützt das eine Event das andere auch, also wird auch gefeuert, wenn das andere auch gefeuert wird. Bin mir allerdings nicht sicher.

Du kannst sonst auch noch versuchen " IsSynchronizedWithCurrentItem="True"" zu setzen.

Kann dir leider nicht weiterhelfen.
 
Zuletzt bearbeitet: (Rechtschreibfehler)
e-Laurin schrieb:
Nachtrag:
Das träge Programmverhalten tritt wirklich nur dann auf, wenn der User die Auswahl in der DragList ändert. Das Programm wird aber sofort wieder reaktionsfreudig, sobald man einfach mal ein Item drag'm'dropped.
Ich raff das nicht. Da muss ein Bug im .Net-Framework vorliegen - vermutlich an einer Stelle, wo er das SelectionChanged-Event in Verbindung mit Touch-Eingaben verarbeitet.

Dann würde ich an deiner Stelle mal versuchen das zu profilen, dann weißt du Bescheid.
 
Nur mal eine Frage. Du schreibst "auf einem Tablet...". Soll das Code für eine "Metro Style" App sein?

Edit.
Falls ja, was ist das? Developer Preview? Auf jeden Fall nicht RC oder RTM.
 
OK, hatte mich schon etwas gewundert ;)
Nur als Tip am Rande. Wenn du sowieso vor hast dich mit "Metro Apps" zu beschäftigen, dann tu es jetzt - der Unterschied ist deutlich größer als man vermuten könnte.
 
Ich habe da schon mal reingeschaut und ich habe erkannt, dass mir noch zu viel Verständnis fehlt. Deshalb will ich erst mal kleine Brötchen backen. Es hat mir auch schon sehr viel gebracht, da ich es allmählich in mein Hirn bekomme, wie die Datenbindung funktioniert und was WPF alles kann.

Dennoch stehe ich gefühlt irgendwie noch sehr weit am Anfang. C# gaukelt einem die Leichtigkeit von Java vor, ist aber mMn ebenso komplex wie C++. *grusel*
Das wird aber schon noch werden. ;)
 
Java und leicht? :D
Da eine UI die auch nur ansatzweise so gut aussieht wie mit WPF zu zaubern ist erst wahrlich grausam! :D

Mit welchem Pattern entwickelst du die Anwendung? MVVM empfinde ich auch deutlich komplexer (was man auch daran erkennt das es so einige Frameworks dafür gibt) als es beispielsweise mit Code Behind ist.

Das Problem bei WPF ist halt das es verhältnismäßig wenig eindeutige Lösung gibt, dafür insgesamt aber immer sehr viele.
 
GUIs in Java sind nur langwierige Fummelarbeit, aber nicht schwierig. ;)

Ich habe auf das simple MVC gesetzt, da es hier nur ein paar Buttons und die erwähnte Drag'n'Drop-Geschichte gibt. MVVM ist MVC ja ziemlich ähnlich (es wird ja "nur" ViewModel eingeführt und vor die View geschnallt, vereinfacht ausgedrückt).
Als schwierig betrachte ich den Funktionsumfang, der mit WPF und .Net verfügbar ist. Da gehe ich im Moment einfach noch hoffnungslos unter der Masse an Möglichkeiten unter. Und dann muss man die "best practise" finden - ojemine.
 
Hast du nen Link zu MVC mit WPF? Ich hab bisher nur MVC mit ASP.NET gemacht und fand das ziemlich geil. Aber mit MVVM bin ich bisher noch nicht warm geworden.
 
Zurück
Oben