Source can only be set from xaml - xamarin.forms

I am setting the source property of ResourceDictionary programatically and not from xaml in a Xamarin forms project.
During run time I always get System.invalidOperation exception with the message "Source can only be set from Xaml.
Resources = Resources ?? new ResourceDictionary();
if(Resources.Source == null)
{
Resources.Source = new Uri("/Styles/ActiveTrackerStyle.xaml", UriKind.Relative);
}
Wondering if I am doing anything wrong while setting the Source. Source property has both getter and setter. Any pointers of what is wrong here.

With the help of a colleague, I got it working:
First: Browsing through the Xamarin.Forms' ResourceDictionary class (here, I saw the following property:
public Uri Source {
get { return _source; }
set {
if (_source == value)
return;
throw new InvalidOperationException("Source can only be set from XAML."); //through the RDSourceTypeConverter
}
It seems that you cannot change the source if the private variable "_source" has been set already;
However, the class also have another method "SetAndLoadSource" and in this method the _source variable is set without any checks. Thus, I got it working by doing the following:
var source = new Uri("/Styles/LightResourceDictionary.xaml", UriKind.RelativeOrAbsolute);
var resourceDictionary = new ResourceDictionary();
resourceDictionary.SetAndLoadSource(source, "Styles/LightResourceDictionary.xaml", this.GetType().GetTypeInfo().Assembly, null);
ThemeDictionary.MergedDictionaries.Add(resourceDictionary);
ThemeDictionary.MergedDictionaries.ElementAt(0).Source = source;
Note that "ThemeDictionary" is the x:Name of my MergedDictionary:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary x:Name="ThemeDictionary">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/DarkResourceDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

Related

MudTable WASM, populating state on page load

Can't find a code sample for this in any of the documentation. Using MudTable ServerData feature, want to store the tables state (page no, page size, sorting) into the url as it changes which Iv'e done:
NavigationManager.NavigateTo($"/list/MyEntity/?PageNo={state.Page}&PageSize={state.PageSize}&SortLabel={state.SortLabel}&SortDirection={(state.SortDirection == MudBlazor.SortDirection.Ascending ? "asc" : "desc")}&Filter={Filter}", false);
However on loading the page, I want to push these parameters into the MudTable
table.CurrentPage = PageNo;
table.RowsPerPage = PageSize;
await table.ReloadServerData();
however I get warnings that I can't use 'table.CurrentPage' outside of component. Any way to implement what I want in current version of MudTable?
Assigning the values to component parameters in code is not the Blazor way. All you need to do is to set them in Razor like this:
<MudTable Items="#Elements" CurrentPage="PageNo" RowsPerPage="PageSize">
...
<PagerContent>
<MudTablePager />
</PagerContent>
</MudTable>
Here is a fiddle to play around with live. It shows that setting the two parameters in razor works. https://try.mudblazor.com/snippet/QaQlvFvLmZkKlaWQ
I think this should do the trick. Sadly, NavigateTo() looks broken.
#inject NavigationManager NavigationManager
<MudTable
#* ... *#
</MudTable>
#code
{
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// on first render, _table is null
if (firstRender)
{
return;
}
var uri = NavigationManager.ToAbsoluteUri(NavigationManager.Uri);
var queryComponents = QueryHelpers.ParseQuery(uri.Query);
queryComponents.TryGetValue("PageNo", out StringValues pageNo);
queryComponents.TryGetValue("PageSize", out StringValues pageSize);
int rowsPerPage = int.Parse(pageSize.First());
int page = int.Parse(pageNo.First());
_table.SetRowsPerPage(rowsPerPage);
//_table.NavigateTo(page); // this is broken
await _table.ReloadServerData();
}
}

JavaFX: ClassNotFoundException for imported class in FXML

I'm trying to create a textfield with a title embedded in the field border like:
Following the solution posted here I've created a .java file called TitledBorder.java within my src>main>java directory. My FXML is in the src>main>resources directory and I've added:
<?import TitledBorder?> at the top and it shows no error like:
I then added this code to the FXML
<HBox prefHeight="100.0" prefWidth="200.0">
<children>
<TitledBorder title="Email" >
<TextField fx:id="emailField" prefHeight="44.0" prefWidth="143.0" />
</TitledBorder>
</children>
</HBox>
and it shows no error either. I then launch my main method which is in a class also in src>main>java but it gets an error in the .fxml saying javafx.fxml.LoadException:
/C:/Users/ME/Documents/Automation/target/classes/demofxml.fxml
and
Caused by: java.lang.ClassNotFoundException
at javafx.fxml.FXMLLoader.loadType(FXMLLoader.java:2899)
I'm not sure why it references "/target/classes/..." as opposed to "/src/main/java/...".
This is the only FXML example I've found so I'm confused why I'm getting an error upon compiling, yet no errors are shown prior? Removing all reference to TitledBorder allows all my code to function/compile properly. Since its in the src package I use this code in FXML to connect w/ controller fx:controller="loadController">. CSS is added properly too.
Thoughts?
The line
<?import TitledBorder?>
implies that you put the TitledBorder.java file to default package (i.e. no package declaration in source code of this file). However FXMLLoader's source code checks the imports in FXML file and splits package path name and class name in loadType(...) below, to load the imported class later with loadTypeForPackage():
private Class<?> loadType(String name, boolean cache) throws ClassNotFoundException {
int i = name.indexOf('.');
int n = name.length();
while (i != -1
&& i < n
&& Character.isLowerCase(name.charAt(i + 1))) {
i = name.indexOf('.', i + 1);
}
if (i == -1 || i == n) {
throw new ClassNotFoundException();
}
String packageName = name.substring(0, i);
String className = name.substring(i + 1);
Class<?> type = loadTypeForPackage(packageName, className);
if (cache) {
classes.put(className, type);
}
return type;
}
// TODO Rename to loadType() when deprecated static version is removed
private Class<?> loadTypeForPackage(String packageName, String className) throws ClassNotFoundException {
return getClassLoader().loadClass(packageName + "." + className.replace('.', '$'));
}
The imported class name is "TitledBorder" so the variable i at the 1st line in loadType method will be evaluated as name.indexOf('.') = -1, and will throw ClassNotFoundException in the next lines of code.
Generally it is bad practice to use default packages. Put the TitledBorder.java into some package and import it as
<?import my.some.package.TitledBorder?>

Bing Maps MapItemsControl throwing E_FAIL exception setting pushpin position

I am trying to add a map to a Windows 8 Store app using the Bing Map SDK and control. With this set of Xaml:
<Page.Resources>
<DataTemplate x:Key="LogoTemplate">
<m:Pushpin m:MapLayer.Position="{Binding Item2}" Text="{Binding Item1}"/>
</DataTemplate>
</Page.Resources>
...
<m:Map Credentials="{StaticResource BingMapsApiKey}" ZoomLevel="12" HomeRegion="US" Heading="2">
<m:MapItemsControl x:Name="ListOfItems"
ItemTemplate="{StaticResource LogoTemplate}"
ItemsSource="{Binding LocationList}">
</m:MapItemsControl>
</m:Map>
Bound to this Property of the view model:
public IEnumerable<Tuple<string, Bing.Maps.Location>> LocationList
{
get
{
if (MapLocation != null)
{
return new List<Tuple<string, Bing.Maps.Location>>
{
new Tuple<string, Bing.Maps.Location>("1", new Bing.Maps.Location(MapLocation.lat, MapLocation.lng))
};
}
return Enumerable.Empty<Tuple<string, Bing.Maps.Location>>();
}
}
It consistently excepts with an E_FAIL HResult from a COM component in Bing maps. With this message in the debugger output window:
WinRT information: Failed to assign to property 'Bing.Maps.MapLayer.Position'
Lat and Long are valid points. I am stumped and cannot see anything to do differently. The interwebs has very little information about the App Store version of the Bing Maps control so am hoping somebody has gotten this to work.
Just in case anybody else has this issue (or also encounters difficulty integrating the windows store version of this control to a MVVM model) it looks like the solution is to wrap the control in a bindable version. I used this code form codeplex with some success so far.
It's simply not possible to data-bind the MapLayer.Position to a Location object, but you can data-bind Latitude and Longitude:
<m:Pushpin Text="{Binding Item1}"/>
<m:MapLayer.Position>
<m:Location Latitude="{Binding Item2.Latitude}" Longitude="{Binding Item2.Longitude}" />
</m:MapLayer.Position>
</m:Pushpin>

child of child movie clip are null in imported object from flex to flash right after being created

I have an Movie Clip in Flash that have subobject of button type which has subobject of input text and movie clips. Right after creation core Moveclip all subobject are set to null, when I expect them to be valid objects.
// hierarchy:
// core:MC_Core_design
// button_1:B_Mybutton
// text_name // dynamic text with instance name
// mc_icon // movie clip with instance name
var core:MC_Core_design = new MC_Core_design();
addChild(core);
core.button_1.text_name.text = "hello world"; // error: text_name is null
core.button_1.mc_icon.visible = false; // error: mc_icon is null
MC_Core_design was created in Flash and exported to Actionscript. I've done this for button_1 class aswell. The code was written using Flex.
When I comment out both lines that result in error I get correct view of the core Movie clip with all subobject.
How can I set subobject properties right after object creation?
You need to listen for the Event.INIT from the class when it is created. (If you are not embedding a symbol using the Embed metatag then Flash takes a few milliseconds to initialize the loaded movieclip). This does not seem to be a problem if the Flash IDE swf/swc does not contain any actionscript)
The issue is sometimes it can be really quick, so it fires the INIT event before you get a chance to attach the event listener to the object. so you can't just attach it after you instantiate the object.
A work around is to embed the swf as a byte array, then use the loader class to load the embedded bytes (This lets you set the event listener before calling load).
e.g.
[Embed(source="assets.swf", mimeType="application/octet-stream")]
private var assetBytes:Class;
private var clip:MovieClip;
private var loader:Loader;
public function LoadBytesExample()
{
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT, onAssetLoaded);
loader.loadBytes(new assetBytes());
}
private function onAssetLoaded(e:Event):void
{
var loader:Loader = (e.currentTarget as LoaderInfo).loader;
(e.currentTarget as LoaderInfo).removeEventListener(Event.INIT, onAssetLoaded);
clip = loader.content as MovieClip;
this.addChild(clip);
clip.someTextField.text = "HELLO WORLD";
}
Sorry for the formatting, just wrote that off the top of my head
And the syntax for embedding the symbol (You won't need to load this via a loader as the actionscript in the external swf/swc is stripped).
[Embed(source="assets.swf", symbol="somesymbol")]
private var assetSymbol:Class;
private var clip:MovieClip;
public function LoadSymbolExample()
{
clip = new assetSymbol();
clip.sometext.text = "Hello World";
}
If I see it right, button_1:B_Mybutton is not yet initialized.
I mean something like : button_1:B_Mybutton = new B_Mybutton();
About the other two variables text_name & mc_icon as you describe if they have been initialized already (as you term them as instance names), Iguess they should not give you any problem.
Also I asssume that you are setting access modifiers to all as public.
If you still have problem... pls share how all the required variables are defined. Just the relevant part would be enough.

XmlWriter - reading an attribute (quick question)

I'm using this for my code, it outputs to the xml file perfectly, but it adds an ' = ' sign after the element name even though only one of my elements has an attribute.
I suppose I could do something like
if(reader.Getattribute != "")
// I made that up on the spot, I'm not sure if that would really work
{
Console.WriteLine("<{0} = {1}>", reader.Name, reader.GetAttribute("name"));
}
else
{
Console.WriteLine("<{0}>", reader.Name);
}
but is there a cleaner way to code that?
My code (without workaround)
using System;
using System.Xml;
using System.IO;
using System.Text;
public class MainClass
{
private static void Main()
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter w = XmlWriter.Create(#"Path\test.xml", settings);
w.WriteStartDocument();
w.WriteStartElement("classes");
w.WriteStartElement("class");
w.WriteAttributeString("name", "EE 999");
w.WriteElementString("Class_Name", "Programming");
w.WriteElementString("Teacher", "James");
w.WriteElementString("Room_Number", "333");
w.WriteElementString("ID", "2324324");
w.WriteEndElement();
w.WriteEndDocument();
w.Flush();
w.Close();
XmlReader reader = XmlReader.Create(#"Path\test.xml");
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
Console.WriteLine("<{0} = {1}>", reader.Name, reader.GetAttribute("name"));
break;
case XmlNodeType.Text:
Console.WriteLine(reader.Value);
break;
case XmlNodeType.CDATA:
Console.WriteLine("<[CDATA[{0}]>", reader.Value);
break;
case XmlNodeType.ProcessingInstruction:
Console.WriteLine("<?{0} {1}?>", reader.Name, reader.Value);
break;
case XmlNodeType.Comment:
Console.WriteLine("<!--{0}-->", reader.Value);
break;
case XmlNodeType.XmlDeclaration:
Console.WriteLine("<?xml version='1.0'?>");
break;
case XmlNodeType.Document:
break;
case XmlNodeType.DocumentType:
Console.WriteLine("<!DOCTYPE {0} [{1}]", reader.Name, reader.Value);
break;
case XmlNodeType.EntityReference:
Console.WriteLine(reader.Name);
break;
case XmlNodeType.EndElement:
Console.WriteLine("</{0}>", reader.Name);
break;
}
}
}
}
Output
<?xml version='1.0'?>
<classes = >
<class = EE 999>
<Class_Name = >
Programming
</Class_Name>
<Teacher = >
James
</Teacher>
<Room_Number = >
333
</Room_Number>
<ID = >
2324324
</ID>
</class>
</classes>
Because this line
case XmlNodeType.Element:
Console.WriteLine("<{0} = {1}>", reader.Name, reader.GetAttribute("name"));
break;
Always writes the '=' without checking.
A rough fix :
case XmlNodeType.Element:
Console.WriteLine("<{0}", reader.Name);
if (reader.HasAttributes)
// Write out attributes
Console.WriteLine(">");
break;
But why are you using the XmlReader at all? It is cumbersome and only useful when dealing with huge Xml streams.
If your datasets are not >> 10 MB then take a look at XDocument or XmlDocument
The XmlWriter in your Example can be replaced by (rough approx):
// using System.Xml.Linq;
var root = new XElement("classes",
new XElement("class", new XAttribute("name", "EE 999"),
new XElement("Class_Name", "Programming"),
new XElement("Teacher", "James")
));
root.Save(#"Path\test.xml");
var doc = XDocument.Load(#"Path\test.xml");
// doc is now an in-memory tree of XElement objects
// that you can navigate and query
And here is an intro
I don't know exactly what you're trying to accomplish but personally I would create a .NET class representing your class element with properties identifying the sub elements then use System.Xml.Serialization.XmlSerializer to write or read it from a file.
Here is an example:
using System.Xml.Serialization;
public class MyClasses : List<MyClass>{}
public class MyClass{
public String Teacher{ get; set; }
}
void main(){
MyClasses classList = new MyClasses();
MyClass c = new MyClass();
c.Teacher = "James";
classList.Add(c);
XmlSerializer serializer = new XmlSerializer(classList.GetType());
serializer.Serialize(/*Put your stream here*/);
}
And, after leaving setting up your stream as an exercise to the reader, blamo, you're done outputing an XML representation of your object to some stream. The stream could be a file, string, whatever. Sorry for nasty C# (if its nasty) I use VB.NET everyday so the syntax and keywords may be a little off.
Update
I added some code to show how to serialize a collection of the classes. If nodes aren't coming out named correctly there are attributes you can add to your class properties, just do a quick google for them.
Update again
Sorry, its hard to explain when we're using the same word to mean two different things. Lets say you're trying to represent a bucket of bricks. You would write a C# class called Brick and a C# class called Bucket that inherited from List<Brick> your Brick would have a property called Color. You would then make all your bricks with different colors and fill the bucket with your bricks. Then you would pass your bucket to the serializer and it would give you something like:
<Bucket>
<Brick>
<Color>
blue
</Color>
</Brick>
</Bucket>
The serializer builds the XML for you from the definitions of your classes so you don't have to worry about the details. You can read more about it here and here

Resources