Xamarin.Forms Windows App load XML data into ListView - c#

I am writing an application in Xamarin.Forms for Android, iOS, and Windows Store. I want to populate a ListView with about 10,000 elements from an XML file. The problem is when I run the code for Windows Phone or Windows Store, the application lags for about a minute before coming back alive and populating the ListView. It populates instantly for Android and iOS. However for Windows, it lags. Could somebody help me fix this problem? Here is my code which does the reading of XML and populating the ListView:
public async void LoadCharacters()
{
Assembly assembly = typeof(CharacterPage).GetTypeInfo().Assembly;
string file = assembly.GetManifestResourceNames().First(x => x.Contains("Characters.xml"));
Stream stream = assembly.GetManifestResourceStream(file);
data = new ObservableCollection<Character>();
await Task.Factory.StartNew(delegate {
XDocument doc = XDocument.Load(stream);
IEnumerable<Character> characters = from query in doc.Descendants("c")
select new Character
{
Simplified = query.Attribute("s").Value,
Traditional = query.Attribute("t").Value,
Pinyin = query.Attribute("p").Value,
English = query.Attribute("e").Value,
URL = query.Attribute("u").Value
};
data = characters.ToObservableCollection();
});
characterList.ItemsSource = data;
}
This code works, and runs smooth in iOS and Android. However in Windows, it hangs for about 1 minutes. Please help.
Thank you

The answer is to set the height of the listview item. Then it loads instantly.

Related

UIAutomation throws AccessViolationException on Windows 11

The issue:
We have an application written in C# that uses UIAutomation to get the current text (either selected or the word behind the carret) in other applications (Word, OpenOffice, Notepad, etc.).
All is working great on Windows 10, even up to 21H2, last update check done today.
But we had several clients informing us that the application is closing abruptly on Windows 11.
After some debugging I've seen some System.AccessViolationException thrown when trying to use the TextPatternRange.GetText() method:
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
What we've tried so far:
Setting uiaccess=true in manifest and signing the app : as mentionned here https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/350ceab8-436b-4ef1-8512-3fee4b470c0a/problem-with-manifest-and-uiaccess-set-to-true?forum=windowsgeneraldevelopmentissues => no changes (app is in C:\Program Files\
In addition to the above, I did try to set the level to "requireAdministrator" in the manifest, no changes either
As I've seen that it may come from a bug in Windows 11 (https://forum.emclient.com/t/emclient-9-0-1317-0-up-to-9-0-1361-0-password-correction-crashes-the-app/79904), I tried to install the 22H2 Preview release, still no changes.
Reproductible example
In order to be able to isolate the issue (and check it was not something else in our app that was causing the exception) I quickly made the following test (based on : How to get selected text of currently focused window? validated answer)
private void btnRefresh_Click(object sender, RoutedEventArgs e)
{
var p = Process.GetProcessesByName("notepad").FirstOrDefault();
var root = AutomationElement.FromHandle(p.MainWindowHandle);
var documentControl = new
PropertyCondition(AutomationElement.ControlTypeProperty,
ControlType.Document);
var textPatternAvailable = new PropertyCondition(AutomationElement.IsTextPatternAvailableProperty, true);
var findControl = new AndCondition(documentControl, textPatternAvailable);
var targetDocument = root.FindFirst(TreeScope.Descendants, findControl);
var textPattern = targetDocument.GetCurrentPattern(TextPattern.Pattern) as TextPattern;
string text = "";
foreach (var selection in textPattern.GetSelection())
{
text += selection.GetText(255);
Console.WriteLine($"Selection: \"{selection.GetText(255)}\"");
}
lblFocusedProcess.Content = p.ProcessName;
lblSelectedText.Content = text;
}
When pressing a button, this method is called and the results displayed in labels.
The method uses UIAutomation to get the notepad process and extract the selected text.
This works well in Windows 10 with latest update, crashes immediately on Windows 11 with the AccessViolationException.
On Windows 10 it works even without the uiaccess=true setting in the manifest.
Questions/Next steps
Do anyone know/has a clue about what can cause this?
Is Windows 11 way more regarding towards UIAutomation?
On my side I'll probably open an issue by Microsoft.
And one track we might follow is getting an EV and sign the app itself and the installer as it'll also enhance the installation process, removing the big red warnings. But as this is an app distributed for free we had not done it as it was working without it.
I'll also continue testing with the reproductible code and update this question should anything new appear.
I posted the same question on MSDN forums and got this answer:
https://learn.microsoft.com/en-us/answers/questions/915789/uiautomation-throws-accessviolationexception-on-wi.html
Using IUIautomation instead of System.Windows.Automation works on Windows 11.
So I'm marking this as solved but if anyone has another idea or knows what happens you're welcome to comment!

C# WPF application crashing when playing 16 players

I am running into an issue with my C# WPF application crashing silently when I am trying to play on 16 VideoViews. I did not see any error messaged popup, nor did I see anything in Windows Event viewer.
Each player instance have WindowsFormHost and hosting a VideoView in that and I am playing RTSP streams on them.
Crash time is not fixed, sometimes it crash after 2 hours, and sometimes after 7-8 hours.
Core.Initialize(AppInfo.VlcDir.FullName);
private LibVLC libVlc = null;
private LibVLCSharp.Shared.MediaPlayer mediaPlayer = null;
this.libVlc = new LibVLC(this.GetParsedPlayerOptions().ToArray());
this.mediaPlayer = new LibVLCSharp.Shared.MediaPlayer(this.libVlc);
this.videoPlayer.MediaPlayer = this.mediaPlayer;
this.mediaPlayer.Volume = 0;
this.mediaPlayer.EnableKeyInput = false;
this.mediaPlayer.EnableMouseInput = false;
// Then I added a bunch of event handlers for VideoView and MediaPlayer.
// Then I have a different function which plays videos
if (this.mediaPlayer != null)
{
var media = new Media(this.libVlc,GetPlaybackStreamUrl(this.Server), FromType.FromLocation);
this.mediaPlayer.Media = media;
this.mediaPlayer.Play();
try
{
media.Dispose();
}
catch
{
}
}
Please let me know if you need any more information.
Any suggestions of what I could be doing wrong, or anything missing?
I am running on Windows 10. Visual Studio 2019, application compiled as X86.
I am not able to find the option to upload log file, but I did attach that to the issue on videolan forum, which can be found here: https://code.videolan.org/videolan/LibVLCSharp/-/issues/564
Thanks.
I was not able to find the problem with the code or the crash stack for where it's dying.
But I was able to fix the problem by increasing the address space, by using editbin to add /LARGEADDRESSSPACE to process post build.

saving files on IOS from a Unity 3D game

Ok, so I followed the tutorial at unity3d.com (located here)
Just so that you dont have to or want to watch the whole video , here is the save/load functions.
//This one saves/creates the file
void OnDisable()
{
BinaryFormatter binFormatter = new BinaryFormatter();
FileStream file = File.Create(Application.persistentDataPath + "/savedgame.dat");
GameData data = new GameData();
data.coinAmount = coinAmount;
data.upgradeLevel = upgradeLevel;
binFormatter.Serialize(file, data);
file.Close();
}
//And this one loads it
void OnEnable()
{
if (File.Exists(Application.persistentDataPath + "/savedgame.dat"))
{
BinaryFormatter binFormatter = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/savedgame.dat",FileMode.Open);
GameData data = (GameData)binFormatter.Deserialize(file) ;
file.Close();
coinAmount = data.coinAmount;
upgradeLevel = data.upgradeLevel;
}
}
I'm using OnDisable/OnEnable so that my game autosaves every time the users exits. This works on a pc and a mac, but when I build it to the Ipad air2 and its like nothing happens. Xcode trows a exception that says unknown filename(-1).
Thanks in advance for the help
Upon further investigation on android it turns out that the file gets created and the game reads data from it. The problems is here :
data.coinAmount = coinAmount;
data.upgradeLevel = upgradeLevel;
For some reason this does not write the correct data when the app runs on Android(probably the same for IOS).
When I supply a hard coded value i.e : data.coinAmount = 100; the game then reads it correctly.
Upon even further investigation turns out that the code work when you call Application.quit but does not work when we "force close" the app i.e using the ipads front button. Need help with this
Ok, so turns out when we stop a Unity game with the home button on a mobile device the methods OnEnable/OnDisable dont seem to we called or working properly. So my solution to the problem is to migrate the save code to the OnApplicationPause(bool pauseStatus) method. After a few tests this seems to be called every time you press the home screen, thus making sure that the game autosaves.
However this only fixed the issue on android devices. Someone please tells me what happens when a IOS user presses the home button so I can freakin save my game when that happens.
Fixed the issue. After some debugging it turns out that ios and .Net JIT do not like each other. This code fixes the issue:
if (Application.platform == RuntimePlatform.IPhonePlayer)
{
System.Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes");
}
I recommend putting it in the Awake() method.

DataContractSerializer fails, null data

I've got some code for Windows Phone 7, for a RSS app:
private RSSSettings DeserializeSettings(string data)
{
RSSSettings rsssettings;
try
{
var ser = new DataContractSerializer(typeof(RSSSettings));
using (var sr = new StringReader(data))
using (var xr = XmlReader.Create(sr))
rsssettings = (RSSSettings)ser.ReadObject(xr);
}
catch (Exception ex)
{
ex.ToString();
rsssettings = new RSSSettings() { Version = -1 };
}
return rsssettings;
}
It works perfectly on Windows Phone 7. I ported the app to Windows Phone 8, and everything else in the app works except for this snippet.
Comparing what happens in Windows Phone 7 and 8, "rsssettings" in WP8 remains null while it populates correctly in WP7. There have been no code changes to this portion of the code at all.
Everything works the same until:
rsssettings = (RSSSettings)ser.ReadObject(xr);
The exception is not called.
Anyone have a clue as to how to resolve this frustrating issue?
Yeah, you're not going to like this.
DataContractSerializer on WP8 requires XML elements be organized alphabetically. That's done since the assumption that everything that goes into DataContractSerializer comes out of another DataContractSerializer.
I wish I was making this up, but I'm not. From MSDN's App platform compatibility for Windows Phone:
DataContractSerializer class
WP8 Behaviour: XML elements must be sorted alphabetically.
WP7 Behaviour: XML elements can be unordered.
There are a few alternatives for you at this point:
̶a̶l̶p̶h̶a̶b̶e̶t̶i̶c̶a̶l̶l̶y̶ ̶o̶r̶d̶e̶r̶ ̶y̶o̶u̶ ̶X̶M̶L̶. No, that's really not an option.
Since it seems like you're getting RSS, you can consider using WCF's System.ServiceModel.Syndication.SyndicationFeed which is specfically built for RSS/Atom. More on this at this great article by Den Delimarsky.
If your using non-RSS XML, consider using straight up Xml Serialization with XmlSerializer. For my money it's the best and simplest way to do over the wire XML serialization and deserialization.
The behaviour change from WP7 to WP8 is enabled via Quirks Mode. Meaning that WP7 apps running on WP8 will still run OK. If your app doesn't benefit from WP8 featuresets, you can keep your entire app as a WP7 app.

live tile is not updating in Windows Phone

i am developing a windows phone app where application has an option to pin the application to home screen. And i am using ShellTileSchedule class to do schedule the update periodically. Some reason my app is not pushing any update to tile. My app data is completely local, no data is coming from outside.
In my tile update, i am not updating any image on the lile, but only changing the data to display.
foreach (ShellTile tile in ShellTile.ActiveTiles)
{
IconicTileData tileData = GetTileData();
tileSchedule = new ShellTileSchedule(tile, tileData);
tileSchedule.Interval = UpdateInterval.EveryHour;
tileSchedule.Recurrence = UpdateRecurrence.Interval;
tileSchedule.Count=GetUserData();
tileSchedule.StartTime = DateTime.Now;
tileSchedule.Start();
tile.Update(tileData);
}
Any help in this regard? Or do i need to background agent to update the tile?
ShellTileSchedule can only pull images off the web, not from the phone itself. This is one of the limitations of ShellTileSchedule. If you want to set background images to resources on the phone, look at using push notifications instead.
Source: http://www.silverlightshow.net/news/WP7-Using-ShellTileSchedule-to-update-your-app-s-Live-Tile-background.aspx
Shouldn't you be setting a ShellTileSchedule.RemoteImageUri somewhere? I mean, that's kinda what ShellTileSchedule is there for, to update your tile image from a remote Uri on a regular interval... See sample of how to use this class for secondary tiles here.
You have to fill the properties of IconicTileData. In your sample you just create empty data structure and use it for the schedule, that won't work. I use it like this:
IconicTileData newTileData = new IconicTileData
{
Title = SharedResources.AppName,
Count = BatteryHelper.BateryLevel,
SmallIconImage = new Uri(#"/Assets/IconicSmall.png", UriKind.Relative),
IconImage = new Uri(#"/Assets/IconicMedium.png", UriKind.Relative),
};

Categories