Using PathIcon from resources results in XamlParseException - windows
Universal Store Project for 8.1 here.
I have a PathIcon declared in a ResourceDictionary like this:
<PathIcon
x:Key="PhoneIcon"
Data="F0 M22,22z M0,0z M17.4,22.533333C19.111111,25.955556,22.044444,28.766667,25.466667,30.6L28.155556,27.911111C28.522222,27.544444 29.011111,27.422222 29.377778,27.666667 30.722222,28.155556 32.188889,28.4 33.777778,28.4 34.511111,28.4 35,28.888889 35,29.622222L35,33.777778C35,34.511111 34.511111,35 33.777778,35 22.288889,35 13,25.711111 13,14.222222 13,13.488889 13.488889,13 14.222222,13L18.5,13C19.233333,13 19.722222,13.488889 19.722222,14.222222 19.722222,15.688889 19.966667,17.155556 20.455556,18.622222 20.577778,18.988889 20.455556,19.477778 20.211111,19.844444L17.4,22.533333 17.4,22.533333z"
/>
I can get this resource in code behind like this:
PathIcon icon1 = null;
object resource;
if (Application.Current.Resources.TryGetValue("PhoneIcon", out resource)) {
icon1 = resource as PathIcon;
};
Alternatively, I can create it like this (avoiding querying resource dictionary):
var icon2 = XamlReader.Load(
#"<PathIcon
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
Data=""F0 M22,22z M0,0z M17.4,22.533333C19.111111,25.955556,22.044444,28.766667,25.466667,30.6L28.155556,27.911111C28.522222,27.544444 29.011111,27.422222 29.377778,27.666667 30.722222,28.155556 32.188889,28.4 33.777778,28.4 34.511111,28.4 35,28.888889 35,29.622222L35,33.777778C35,34.511111 34.511111,35 33.777778,35 22.288889,35 13,25.711111 13,14.222222 13,13.488889 13.488889,13 14.222222,13L18.5,13C19.233333,13 19.722222,13.488889 19.722222,14.222222 19.722222,15.688889 19.966667,17.155556 20.455556,18.622222 20.577778,18.988889 20.455556,19.477778 20.211111,19.844444L17.4,22.533333 17.4,22.533333z""
/>"
) as PathIcon;
Both ways get me a PathIcon instance that looks just fine (icon1 and icon2 seem to be identical).
Debug.WriteLine(
"{0} equals {1}: {2}",
icon1.Data.Bounds, icon2.Data.Bounds,
icon1.Data.Bounds.Equals(icon2.Data.Bounds)
); // outputs 13,13,22,22 equals 13,13,22,22: True
I'm trying to use the icon for an AppBarButton:
SomeCommandBar.PrimaryCommands.Add(new AppBarButton(){
Label = "Label",
Icon = icon1 or icon2,
Command = SomeCommand
});
The problem is: when I use icon2 (created with XamlReader), everything works just fine, but when I use icon1 (fetched from resourcedictionary), I get a XamlParseException:
"Failed to assign to property '%0'. [Line: 0 Position: 0]"
I'd appreciate any ideas as to why this may be happening.
UPDATE
This doesn't work either (the error is the same as above):
<Page.BottomAppBar>
<CommandBar>
<AppBarButton
Label="Test"
Icon="{StaticResource PhoneIcon}"
/>
</CommandBar>
</Page.BottomAppBar>
So, I guess, there's no way this can work at all. It simply doesn't work with static resource in this place. Guess I'll have to store string resources with icons and XmlReader.Load() them every time, as Chris W. suggested in the comments.
HOWEVER
The following does work for some reason (not that it's useful in any way):
PathIcon icon1 = null;
object resource;
if (Application.Current.Resources.TryGetValue("PhoneIcon", out resource)) {
icon1 = resource as PathIcon;
// if the resource is removed from the dictionary before it is used,
// no exception is thrown.
foreach(var m in Application.Current.Resources.MergedDictionaries) {
if (m.ContainsKey("PhoneIcon")) {
m.Remove("PhoneIcon"); // This does it
}
}
};
I find that the data path is far more complex in the declarative XAML of resources than the implicit converter of the Data property. Since you have it working as a Data property, let Visual Studio do the work. Open the properties dialog in the XAML designer and click the small right square (it will be black at first) net to the Data property and select "Make Resource". The resulting wizard will guide you, and you will see the data string is converted into its component parts and will work with way you want it to after you do this.
Best of luck.
Related
Does the ace core classes keep track of all of the editor instances on a page?
I'm planning on having multiple ace editor instances on a page and I'd like to know if the core libraries are keeping track of them so I can easily get a reference to them later. If not, would keeping the editor instances in a dictionary or object be a good way to do it? Could I create an object on the ace class and should they be by reference or id? var editor1 = ace.edit("myEditorDivID"); var editor2 = ace.edit("myEditorDivID2"); var editors = ace.editors; console(editor1==editors["myEditorDivID"]); // true console.log(editors["myEditorDivID"]); // editor1 var editorIds = ace.editorIds; console.log(editorIds[0]); // myEditorDivID And is there an ace destroy method that should be used to remove references to these instances? Nevermind on part two of this question. I just found the destroy methods: editor.destroy(); editor.container.remove(); Update: I just thought of something else. If we can keep track of the id's or references we can prevent same id collisions. It can also help track how many editors are on a page or if multiple are being created by accident. I just looked at the ace source and don't see anything keeping track of the editors as they are created. Should I try to whip something up or let someone else tackle it? Update 2: I'm thinking to add an editors property and set it by id. I've added an answer with a suggestion.
Answering my own question, no, it does not. But I suggest the following Pseudo code: ace.addEditorById = function (id, editor) { if (ace.editors[id]!=null) throw Error ("Editor already created"); ace.editors[id] = editor; } ace.getEditorById = function (id) { return ace.editors[id]; } ace.removeEditorById = function (id) { var editor = ace.editors[id]; if (editor) { editor.destroy(); editor.container.remove(); delete ace.editors[id]; } } ace.editors = {}; // then when I create an editor I use the following code: editor = ace.edit("editor1"); ace.addEditorById(editor); editor2 = ace.edit("editor2"); ace.addEditorById(editor2); Maybe the editor can be added in the edit call. What do you think?
displaying images from an ArrayCollection in ListItemRenderer in flex
I am facing the following problem, I have an object called "data". It has three properties, one of it being itemRendererData. The "itemRendererData" is an ArrayCollection of objects having many properties one of which is the property "imageURL" (datatype:String). I am working in flex. I have defined the view and the item renderer properly. The view has the data. I am supposed to get the images from the url specified by imageURL property. In the itemRenderer, I have declared, source source = {data.itemRendererData.imageURL} But the images are not being displayed.
Use a the FlexEvent.DATA_CHANGE handler rather than binding, which is actually the proper way to handle this and gives you far more control. public function CustomItemRenderer() { this.addEventListener(FlexEvent.DATA_CHANGE, this.dataChangeHandler); this.addEventListener(FlexEvent.CREATION_COMPLETE, this.creationCompleteHandler); } private function creationCompleteHandler(e:FlexEvent) { if (this.data) { this.image.source = this.data.itemRendererData.imageURL; } } private function dataChangeHandler(e:FlexEvent) { if (this.data && this.initialized) { this.image.source = this.data.itemRendererData.imageURL; } } You will notice that I have a handler for FlexEvent.CREATION_COMPLETE as well. This is because the data is actually set before the components are created. So the first time a renderer is loaded, this.image is null and this.image.source will error out. If that doesn't work, you also need to make sure that the Image/BitmapImage is not a direct child of the renderer. I never did figure out why this was, but adding it as a child of Group fixed that issue where the image was being set but not rendering. Again, I have no idea why this was and I tested for a few hours trying to figure it out. As an added tip, avoid MXML-based ItemRenderers in mobile applications. They are noticeably slower than pure-AS3 renderers.
ViewModels and IsolatedStorageSettings
Im working on a MVVM Windows phone app that displays weather info. When the app loads up it opens MainPage.xaml. It makes a call the the service to get weather info and binds that data to the UI. Both Fahrenheit and Celcius info are returned but only one is displayed. On the setting page, the user can select to view the temp in either Fahrenheit or Celcius. The user can change this setting at any time and its stored in IsolatedStorageSettings. The issue Im having is this: when the user navigates to the Settings page and changes their preference for either Fahrenheit or Celcius, this change is not reflected on the main page. This issue started me thinking about this in a broader context. I can see this being an issue in ANY MVVM app where the display depends on some setting in IsolatedStorage. Any time any setting in the IsoStore is updated, how does the ViewModels know this? When I navigate back in the NavigationStack from the settings page back to MainPage how can I force a rebind of the page? The data in my model hasnt changed, only the data that I want to display has changed. Am I missing something simple here? Thanks in advance. Alex
Probably you have code like this: public double DisplayTemperature { get { return (IsCelsium) ? Celsium : Fahrenheit; } } And IsCelsium is: public double IsCelsium { get { return (bool)settings["IsCelsium"]; } set { settings["IsCelsium"] = value; } } So you need to add NotifyPropertyChanged event to notify UI to get new values from DisplayTemperature property: public double IsCelsium { get { return (bool)settings["IsCelsium"]; } set { settings["IsCelsium"] = value; NotifyPropertyChanged("DisplayTemperature"); } }
Take a look at Caliburn Micro. You could implement something similar or use CM itself. When using CM I don't even think about this stuff, CM makes it so simple. When your ViewModel inherits from Screen there are life-cycle events that fire that you can override. For example, OnInitialize fires the very first time the ViewModel is Activated and OnActivate fires every time the VM is activated. There's also OnViewAttached and OnViewLoaded. These methods are the perfect place to put logic to populate or re-populate data. CM also has some special built in features for allowing one to easily tombstone a single property or an entire object graph into Iso or phone state.
ok, so Ive come up with a solution. Before I get to it, let me provide some background. The app that Im working on uses both MVVM Light and WP7Contrib. That being the case, I am using Funq for DI and the MVVMLight Toolkit. After I posted my initial question, I gave the question a bit more thought. I remembered a video that I watched a while back from MIX2011 called Deep Dive MVVM with Laurent Bugnion http://channel9.msdn.com/Events/MIX/MIX11/OPN03 In it, he talks about just this problem (view models not living at the same time) on Windows Phone. The part in question starts around the 19 minute mark. Anyway, after I remembered that and realized that the ViewModel locator is exposed in App.xaml, this became a trivial problem to solve. When the user changes the Fahrenheit/Celcius option on the setting page, I simply get a reference to the MainViewModel via the ViewModelLocator and reset the collection that is bound to the UI thus causing the bindings to update. public bool AddOrUpdateValue(string Key, Object value) { bool valueChanged = false; // If the key exists if (settings.Contains(Key)) { // If the value has changed if (settings[Key] != value) { // Store the new value settings[Key] = value; valueChanged = true; } } // Otherwise create the key. else { settings.Add(Key, value); valueChanged = true; } return valueChanged; } public bool ImperialSetting { get { return GetValueOrDefault<bool>(ImperialSettingKeyName, ImperialSettingDefault); } set { if (AddOrUpdateValue(ImperialSettingKeyName, value)) { Save(); RaisePropertyChanged("ImperialSettingText"); var vml = new ViewModelLocator(); vml.MainViewModel.Cities = (App.Current as App).Cities; } } } It was a mistake on my part not to realize that I could get access to the viewModel via the ViewModelLocator. Hopefully this post saves someone else the time I burned on this issue.
Populating a dropdown list in Flash Builder
I'm currently using the following code in Flash Builder to return a list of variables from an XML file: [Bindable] private var I_Authors:ArrayCollection = new ArrayCollection (); private function init():void { var param:Object = new Object(); param.action = "getAuthorXML"; authorService.send(param); } protected function authorService_resultHandler(event:ResultEvent):void { I_Authors = event.result.authors.author; } My problem is making use of this data in a dropdown list. I have no trouble putting it into a data grid using dataProvider="{I_Authors}" and dataField="ID" etc., but all the attempts I've made to put a specific field (ID) into a dropdown list have resulted in "object Object". I'm just starting out with flash builder so its probably a basic question but all of the tutorials I've followed on Adobe's website don't seem to be any help. Would appreciate any advice.
Turns out you use labelField="" , just incase anyone else is a bit confused about this. <s:DropDownList id="dropdownList" dataProvider="{________}" labelField="________"></s:DropDownList>
The problem is "author" is an object. When you get your results from authorService you receive an object I_Authors = event.result.authors.author; So you have an array of objects. You probably want to get property of your object eg.: author.ID I_Authors = event.result.authors.author.ID; So you have an array of author ID. dataProvider= I_Authors Let me know if it wasn't clear and you need more explanation.
Visual Studio 2010 plugin / code to clear "Error List" warnings before each build
VS2010 is driving me nuts: whenever I rebuild, the "Error List" warnings from the previous compilation are persisted and any new warnings are simply added to the end of the list. Over time, this list becomes ridiculously long and unwieldy. I'm using the Chirpy 2.0 tools to run JSHint and JSLint on my JS files, and these tools generate a lot of false positives. I've been looking for an easy way to clear the contents of this window, but the only manual mechanism that works 100% of the time is to close and re-open the solution. Not very elegant. I'd like to write a small VS Plug-In or some code that gets called right before a compilation to clear out this list so I can focus only on new warnings for the currently loaded file(s). I see a .Clear() method for the Output window but not for the Error List. Is this doable?
Once upon a time I was an Add-In/VSIX Package/MEF developer ... The answer is shortly no, but I have to do it on the long way: Add-Ins, packages (Managed or not) have access to the VS service level separatedly. Every error belongs to the reporter (If they are manage them as Chirpy do), so you can not handle the errors created by Chirpy 2.0 I take a several look to it's source code and it is persist it's erros gained by the tools in a Singleton collection called TaskList. The deletion of the collection elements is happening in several point of code in the latest release through the RemoveAll method: First: after the soulution is closed. by this: private static string[] buildCommands = new[] { "Build.BuildSelection", "Build.BuildSolution", "ClassViewContextMenus.ClassViewProject.Build" }; private void CommandEvents_BeforeExecute(string guid, int id, object customIn, object customOut, ref bool cancelDefault) { EnvDTE.Command objCommand = default(EnvDTE.Command); string commandName = null; try { objCommand = this.App.Commands.Item(guid, id); } catch (System.ArgumentException) { } if (objCommand != null) { commandName = objCommand.Name; var settings = new Settings(); if (settings.T4RunAsBuild) { if (buildCommands.Contains(commandName)) { if (this.tasks != null) { this.tasks.RemoveAll(); } Engines.T4Engine.RunT4Template(this.App, settings.T4RunAsBuildTemplate); } } } } As you may see, clear of results depends on many thigs. First on a setting (which I don't know where to set on GUI or configs, but seems to get its value form a check box). Second the array of names which are not contains every build commands name. So I see a solution, but only on the way to modify and rebuild/redepeloy your own version from Chirpy (and make a Pull request): The code souldn't depend on the commands, and their names. (rebuilds are missing for example) You could change the method above something like this: this.eventsOnBuild.OnBuildBegin += ( scope, action ) => { if (action != vsBuildAction.vsBuildActionDeploy) { if (this.tasks != null) { this.tasks.RemoveAll(); } if (settings.T4RunAsBuild && action != vsBuildAction.vsBuildActionClean) { Engines.T4Engine.RunT4Template(this.App, settings.T4RunAsBuildTemplate); } } }; Or with something equivalent handler method instead of lambda expression. You shold place it into the subscription OnStartupComplete method of Chirp class. The unsubscription have to placed into OnDisconnection method in the same class. (As for all other subscribed handlers...) Update: When an Add-In disconneced, it isn't means the Studio will be closed immediately. The Add-In could be unloaded. So you should call the RemoveAll from OnDisconneconnection too. (Or Remove and Dispose the TaskList...) Update2: You can also make a custom command, and bind it to a hotkey.