@Abt: Ja, das ist klar. Aber wie setzt man das im Fall einer CollectionView um? VirtualScrollView gibt es bei Maui scheinbar nicht oder ich hab da zumindest noch nichts gefunden.
Ich hab jetzt testweise übrigens das Projekt aus dem oben genannten Ticket genommen und ausprobiert. Das läuft zwar nicht flüssig, aber man kann es immerhin bedienen, was bei meinem Projekt schon nicht mehr geht. Also minimal angepasst und statt der Beispielbilder hab ich die Bilder aus meinen Quellen genommen und man kann es immer noch bedienen.
Jetzt hab ich den Verdacht, dass es irgendwie mit dem Binding zusammenhängt. Aber das ist nur ein Verdacht. Ich werde jetzt auf jeden Fall mal das Fremdprojekt step für step so erweitern, dass es meinem Projekt entspricht. Irgendwo muss der Knackpunkt ja sein, der das ganze unbedienbar macht
@Th69: Danke für die Antwort...
Guter Ansatz, dass ich das mal mit weniger Bildern probieren 😃. Ja... Bis 50 Bilder läuft es noch flüssig. Ab 60 wird es ein bisschen hakelig und ab 80 ist es nicht mehr bedienbar.
Die Bilder liegen direkt als 150x150 JPG vor. Werden also nicht mehr codeseitig skaliert. Das hab ich schonals ersten Ansatz vorgearbeitet, weil ich dachte, dass die Skalierungsarbeit evtl. Probleme machen könnte. Hat aber nichts geändert.
Hallo zusammen,
ich versuche aktuell eine Anwendung, die ich mal mit Angular und Ionic entwickelt habe, mit Maui neu zu programmieren. Es geht dabei um eiune Verwaltung von Hörbüchern. Ziel ist, dass ich die gleiche Anwendung (Codebasis) sowohl unter Android als auch unter Windows verwenden kann.
Eine Ansicht davon ist eine Liste mit allen Covern der registrierten Hörbüchern. Die Cover werden in einem CollectionView angezeigt. Unter Windows ist das kein Problem. Aber unter Android ist es unmöglich in der Liste zu scrollen.
Die Cover sind dabei als Bild-Datein auf dem jeweiligen Gerät vorhanden. Im Image verwende ich einen FileImageSource mit Bindung auf den jeweiligen Pfad zur Bilddatei.
Hier der Xaml-Code
<CollectionView ItemsSource="{Binding Audiobooks}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="models:Audiobook">
<VerticalStackLayout Padding="15">
<Image WidthRequest="150" HeightRequest="150">
<Image.Source>
<FileImageSource File="{Binding ImagePath}" />
</Image.Source>
</Image>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" Span="{Binding Columns}" />
</CollectionView.ItemsLayout>
</CollectionView>
Wie gesagt: Unter Windows keine Probleme. Es handelt sich hier um ca. 300 Bilder alle in der Größe 150x150 Pixel.
Unter Android bewegt sich der Scrollview 10 10 Sekunden vielleicht um einen Pixel. Also absolut nicht bedienbar.
Im Logcat hab ich immer Meldungen in dieser Art:
[Choreographer] Skipped 218 frames! The application may be doing too much work on its main thread.
[EGL_emulation] app_time_stats: avg=1919.20ms min=165.86ms max=3672.54ms count=2
[OpenGLRenderer] Davey! duration=3854ms; Flags=0, FrameTimelineVsyncId=126296, IntendedVsync=1178942486484, Vsync=1179109153144, InputEventId=0, HandleInputStart=1179117296448, AnimationStart=1179117309748, PerformTraversalsStart=1179117329048, DrawStart=1182617312148, FrameDeadline=1179125819810, FrameInterval=1179116961548, FrameStartTime=16666666, SyncQueued=1182636644548, SyncStart=1182642993148, IssueDrawCommandsStart=1182768628148, SwapBuffers=1182770803848, FrameCompleted=1182803662348, DequeueBufferDuration=13300, QueueBufferDuration=254500, GpuCompleted=1182803662348, SwapBuffersCompleted=1182771395948, DisplayPresentTime=0, CommandSubmissionCompleted=1182770803848,
[OpenGLRenderer] Davey! duration=3807ms; Flags=0, FrameTimelineVsyncId=126311, IntendedVsync=1179125819810, Vsync=1182759152998, InputEventId=0, HandleInputStart=1182769331548, AnimationStart=1182769392948, PerformTraversalsStart=1182769805048, DrawStart=1182770136148, FrameDeadline=1182825819662, FrameInterval=1182768873148, FrameStartTime=16666666, SyncQueued=1182770324948, SyncStart=1182779469248, IssueDrawCommandsStart=1182926049948, SwapBuffers=1182927572448, FrameCompleted=1182942847248, DequeueBufferDuration=16100, QueueBufferDuration=185900, GpuCompleted=1182942847248, SwapBuffersCompleted=1182927938848, DisplayPresentTime=0, CommandSubmissionCompleted=1182927572448,
[audiobooks.maui] Explicit concurrent copying GC freed 3501(160KB) AllocSpace objects, 0(0B) LOS objects, 49% free, 10MB/20MB, paused 236us,36us total 14.939ms
Für mich sieht es so aus, als ob das Rendern im MainThread so extrem viel Performance braucht und daher die UI blockiert. Gibt es eine Möglichkeit, das Rendern irgendwie in einen Thread zu verschieben? Bzw. gibt es eine andere, performantere Anzeige-Möglichkeit unter Android?
Ich bin für jeden Tipp dankbar 😉
Hallo zusammen,
ich wollte mir gerade das Auslesen von Attributen über die Methode GetCustomAttributes genauer ansehen und sehen, wie der Parameter inherit richtig verwendet wird, Dabei bin ich über folgende Fälle gestolpert, die ich eigentlich anders erwartet hätte:
[MyAttribute("BaseClass")]
public class BaseClass { }
[MyAttribute("ChildClass")]
public class ChildClass : BaseClass { }
wenn ich hier über die ChildClass die Attribute abrufe wird mit Parameter inherit = true nur das Attribut gefunden, dass bei der ChildClass verwendet wurde. Das Attribut über BaseClass wird nicht gefunden.
typeof(ChildClass).GetCustomAttributes(true);
Ich hätte hier eigentlich erwartet, dass beide Attribute gefunden werden. Verstehe ich das falsch? Gibt es vielleicht auch eine Möglichkeit, dass man beide Attribute findet?
Der zweite Fall hat mich dann richtig stutzig gemacht:
[MyAttribute("IBaseInterface")]
public interface IBaseInterface { }
public class ChildClass : IBaseInterface { }
wenn ich hier auf ChildClass die Attribute suche, wird gar nichts gefunden. Da hätte ich erwartet dass das Attribute von IBaseInterface gefunden wird.
typeof(ChildClass).GetCustomAttributes(true);
Wenn ich statt dem Interface eine Basisklasse verwende, wird das Attribut entsprechend gefunden. Von daher hätte ich das gleiche Verhalten auch erwartet, wenn ich stattdessen ein Interface verwende.
Warum schreibe ich das hier? In meinen Augen sind das zwei Fälle, über die man gerne mal stolpern könnte. Daher würde ich gerne versuchen, die Hintergründe zu verstehen, damit ich mir das leichter merken kann. Vielleicht hat da jemand ein paar Informationen dazu.
Da muss man ein bisschen "Bugusing" betreiben 😃
Man kann statt einem Int64 auch einen String in qword reinschreiben und damit funktioniert es dann
[Registry]
Root: "HKLM64"; Subkey: "SOFTWARE\Name\{#MyAppName}"; ValueType: qword; ValueName: "TStamp"; ValueData: "{code:GetTimestamp}"; Flags: createvalueifdoesntexist
[Code]//Unix Timestamp
function GetUnixTimestamp(ATimerPtr: Int64): Int64;
external 'time@msvcrt.dll cdecl';
function GetTimeStamp: string;
var
value:int64;
begin
value := GetUnixTimeStamp(0);
Result := IntToStr(value);
end;
Was ich mich aber eher frage... Gibt es nicht auch in Inno eine Funktion für den UnixTimestamp?
Hallo zusammen,
wenn man in einem Programmnamen das Wort "Install" verwendet, geht Windows scheinbar automatisch davon aus, dass es sich um ein Installationsprogramm handelt. Unter gewissen Umständen (ich glaub, wenn sich die Installationsdatenbank nicht verändert), wird dann am Ende gefragt, ob das Programm richtig installiert wurde.
Kann man diese Rückfrage von Windows irgendwie umgehen? Eine bestimmte Signatur ins Programm einfügen oder was weiß ich. Vielleicht hat da jemand eine Idee.
ich weiß: Die einfachste Möglichkeit ist, dass man das Programm einfach umbenennt, aber vielleicht gibt es ja was anderes nettes.
Vielen Dank schon mal
Kürzeste Antwort: .net core.
(zB
> )
Aber da steht auch drin, dass man von project.json auf msbuild wechseln will.
The .NET Core tooling is going to move from project.json to MSBuild-based projects in a future release. The recommendation is to still use project.json files for new .NET Core projects since there will be a path to convert your project to MSBuild when the tooling is released.
okay, bis auf den Bezug auf den Namen (javascript object notation, hat nichts mit Java zu tun. Und json selbst ist halt inzwischen DAS universelle serialisierte Datenaustauschformat)
Ich wollte damit auch nicht sagen, dass es was mit java zu tun (Ok, ich hab ein Leerzeichen zuviel drin). Aber json kommt definitiv von Javascript.
Für den Datenaustausch ist es auch vollkommen in Ordnung. Da bringt json natürlich viele Vorteile mit sich, weil man relativ problemlos zwischen verschiedenen Architekturen austauschen kann.
Aber eine Konfigurationsdatei hat meiner Meinung nach nicht viel mit Datenaustausch zu tun.
Also warum json in .NET Entwicklung empfohlen wird, versteh ich ehrlich gesagt nicht. Allein schon vom Namen her (Java Script Object Notation) ist eigentlich schon klar, wo json hingehört.
Json finde ich als Konfigurations-Format absolut untauglich, da es meiner Meinung nach (und auch nach der Meinung meiner meisten Kunden) schlecht lesbar ist und daher auch schwierig zu bearbeiten ist.
XML ist in .NET viel leichter zu verarbeiten. Es gibt nativ alle Methoden dafür, die man benötigt und man braucht keine zusätzliche Komponente. Klar ist XML ziemlich aufgebläht, aber wir reden hier nur von einer Konfigurations-Datei. Da spielen meiner Meinung nach ein paar Byte mehr oder weniger keine Rolle.
Aber auch bei XML hatte ich schon Probleme mit Kunden, weil sie damit nicht umgehen können.
Für den absoluten DAU ist meistens wirklich eine INI-datei mit entsprechenden Kommentaren am leichtesten zu verstehen und kann vom Kunden auch am ehesten bearbeitet werden. Ein kleiner Parser dafür ist auch mit einfachen Mitteln (Regex und Co) schnell erstellt und gegebenfalls gibt es dafür auch einige gute Komponenten, die das Leben damit gewaltig vereinfachen.
Wenn jetzt jemand behauptet, dass eine Config-Datei ja auch nicht für den Kunden lesbar sein muss, weil man dafür in der Regel eine Konfigurations-Oberfläche bereitstellt, dem geb ich natürlich recht. Aber dann brauch ich auch kein Textformat um die Konfiguration zu speichern, sondern dann speicher ich die Konfiguration binär als Object-Dump und gut ist.
Im Grunde kommt es immer auch die Anforderung an, die der Kunde stellt.
Meine persönliche Empfehlung ist XML. Ich habe eine Objekt (static oder singleton), in dem alle bekannten Properties enthalten sind und im Konstruktor dieses Objekts wird die Konfigurations-Datei gelesen und per Linq2Xml verarbeitet und die einzelnen Properties gefüllt. Fertig ist die Wurst. Wenn man noch die Möglichkeit zur Änderung der Konfiguration einbaut, gibt es dann eben noch eine SaveToXml Methode, die die Properties dann eben wieder in ein Xml packt und das Ganze wegschreibt.
Alternativ kann man auch noch per Serialisierung das Ganze ein bisschen vereinfachen.
Vielleicht ein bisschen ungünstig ausgedrückt...
Ich möchte eine Editorkomponente erstellen, wie es bei ToolStrip oder MenuStrip auch der Fall ist. Das heißt, dass ich im Designer die Möglichkeit bieten möchte, dass man direkt Menüpunkte hinzufügt und bearbeitet.
Beim ToolStrip zum beispiel wird ja im Designer eine Schaltfläche angezeigt, über die man Komponenten zum ToolStrip hinzufügen kann und dann auch entsprechend die Events setzen kann.
Mir fehlt da allerdings vollkommen der Ansatz, wie man so etwas macht.
Hallo zusammen,
ich möchte gerade eine eigene Menükomponente erstellen. Diese beinhaltet Items auf nur zwei Ebenen. Zum einen eine Liste von "HeaderItems" und die beinhalten jeweils eine Liste von "NavItems"
Die beiden Klassen "HeaderItem" und "NavItem" leite ich jeweils von System.ComponentModel.Component ab.
(Code ganz stark vereinfacht)
public class HeaderItem: Component
{
public HeaderItem()
{
Items = new List<NavItem>();
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public List<NavItem> Items { get; set; }
...
}
public class NavItem: Component
{
public string Text { get; set; }
public event EventHandler Click;
}
So weit so gut. Damit kann ich dann, wenn meine Komponente in den Designer ziehe, meine HeaderItems anlegen und bei denen jeweils die dazugehörigen Items.
Aber um den EventHandler zu setzen, kann ich nur in der Komponentenleiste unter dem FormDesigner die einzelnen Komponenten anklicken und dann bearbeiten.
Wie kann man einen Editor realisieren, wie es zum Beispiel bei ToolStrip oder beim MenuStrip der Fall ist? Kennt jemand dazu vielleicht ein Tutorial?
Oder sollte man dafür einen ganz anderen Weg gehen?