I have an observable collection of objects in my VM. I want to bind to a property of a specific item in the list in a text block, something like this:
Binding="{MyVMCollection[0].Description}"
But this syntax does not work. Is it possible to do what I am after and if so, how?
Thanks!
You're missing the Binding keyword and I think you also need to use Path.
Binding="{Binding Path=MyVMCollection[0].Description}"
The type of the object needs to be a type where an array index would normally work for this to work. I'm not sure the exact constraints but use Type[] if in doubt.
eg. If it is some weird enumerable type like IOrderedEnumerable<T> (or some wierd LINQy type) then something like {Binding List[0]} won't work.
Related
If I have:
<!--/*#thymesVar id="someCollection" type="java.util.List"*/-->
How would I specify the type of objects in the collection?
I don't see anything on SO or the Idea docs about it.
Oh, it's as simple as specifying the class in the declaration:
<!--/*#thymesVar id="someCollection" type="java.util.List<com.domain.my.Bean>"*/-->
I am trying to populate a dependency property from XAML. The dependency property is an IEnumerable<KeyAction> where KeyAction is a complex type.
<loc:MyType.KeyActions>
<loc:KeyAction Action="Show" Key="Space" Modifiers="LeftCtrl" />
<loc:KeyAction Action="Hide" Key="Escape" />
</loc:MyType.KeyActions>
Now, this causes the KeyAction property to be 'declared twice' because XAML interprets each item as a candidate for the property, instead of items in a list.
For this to work, it would need to look something like:
<loc:CompletionPopupView.KeyActions>
<sys:List`KeyAction>
<loc:KeyAction Action="Show" Key="Space" Modifiers="LeftCtrl" />
<loc:KeyAction Action="Hide" Key="Escape" />
</sys:List`KeyAction>
</loc:CompletionPopupView.KeyActions>
And I'd need to add namespaces, and the generic syntax is probably even more terrible, if even doable. Is there any way to make the first example work?
There are two different ways you can make this work. One looks exactly like your first example, but requires changes to your class and doesn't operate quite the way you're asking for (which might or might not be a problem to you); the other acts exactly like you're asking but is a little more verbose. You can decide which one is better for you.
Option 1: Adding to a collection
XAML has magic shorthand syntax for initializing collections, using the exact syntax you show in your first example. However, it only works if the property type implements IList. (Yes, that's really the non-generic IList -- not normally a big deal though, all the generic collections that ship with .NET implement both IList<T> and IList.)
So you could do your first example, but only if your KeyActions property was declared as a type that implements IList. For example, you could change your property to:
public ObservableCollection<KeyAction> KeyActions { get {...} }
And then just put multiple child elements inside your property, and it would add them to the collection:
<loc:MyType.KeyActions>
<loc:KeyAction Action="Show" Key="Space" Modifiers="LeftCtrl" />
<loc:KeyAction Action="Hide" Key="Escape" />
</loc:MyType.KeyActions>
This isn't quite like what you asked for though, because the XAML doesn't create a new collection -- it adds to the existing collection. So if you choose this option, your class needs to instantiate the collection in its constructor (KeyActions = new ObservableCollection<KeyAction>();), so that you don't get a null reference exception when you start trying to Add elements to it.
Option 2: Creating a new collection
If you do need to create a new collection and assign it to your property, that's doable too. Unfortunately, XAML2006 (the flavor still used by WPF) only supports generics on the root element of the entire document -- so you can't instantiate a List<T> and assign it to a property.
But that's okay; you can use the same workaround that WPF does. Just create your own non-generic class that descends from a generic list.
public class KeyActionCollection : ObservableCollection<KeyAction> {}
Then you can instantiate it in XAML:
<loc:CompletionPopupView.KeyActions>
<loc:KeyActionCollection>
<loc:KeyAction Action="Show" Key="Space" Modifiers="LeftCtrl" />
<loc:KeyAction Action="Hide" Key="Escape" />
</loc:KeyActionCollection>
</loc:CompletionPopupView.KeyActions>
If you choose this option, you can keep your property declared as IEnumerable<KeyAction> if you wish. The custom list is only necessary to populate the list from XAML.
You could even combine both approaches: make the property read/write and of type KeyActionCollection, instantiate it in your constructor, and then XAML can choose whether to add to the existing collection using the shorthand syntax, or create a new collection; and runtime code could make the same choice.
I'm trying to implement this using Eugene Akinshin's code from here: http://forums.silverlight.net/t/237947.aspx/1
It seems like a really nice way to bind to already-existing properties and means the configuration can all be defined in XAML.
However, I can't get it to work.
I'm defining the templates to use like this:
<Converters:TemplateSelectorConverter x:Key="templateConverter">
<Converters:TemplateSelectorCase TemplateReference="Minimised" Template="{StaticResource SmallOrders}"/>
<Converters:TemplateSelectorCase TemplateReference="Restored" Template="{StaticResource MediumOrders}"/>
<Converters:TemplateSelectorCase TemplateReference="Maximised" Template="{StaticResource LargeOrders}"/>
</Converters:TemplateSelectorConverter>
and then setting the item template of my ListBox like this:
ItemTemplate="{Binding CurrentState, Converter={StaticResource templateConverter}}"
CurrentState is a string of either 'Minimised', 'Maximised' or 'Restored' (I've edited the linked example to have a string as the key rather than an int) and is set to 'Minimised' by default, but all I get is a list of Cannot create [my object type] in my ListBox.
The templates definitely work as I can expose the View in the ViewModel and set the DataTemplate in code, and there are visual states that rely on the same CurrentState property which work, so I know the View can access the property correctly. Unfortunately, if I breakpoint the Convert() method in the converter, it never gets hit.
All suggestions greatly appreciated!
Not sure if you have figured this out or not but placement of the Converter definition in the Resource in relationship to the DataTemplate will be the difference between it working and not working.
The Converter needs to be placed prior to the Data Template.
I have a custom silverlight control, which exposes a property with DataGridLength type. Now I want that property to have the same editor as a common DataGridColumn's Width property, with the combobox and everything, like this:
instead, I only get a simple TextBox, with "Auto" written in, with no way to set to SizeToCells and so on.
I assume I need a DesignTime attribute, but none of the ones I found in ComponentModel namespace even came close...
I guess you just have to create an Enum with the all the values autorized (Pixels, SizeToCells, etc ...), you that Enum as the type of your property DataGridLength and then, in the code of your control, take the corresponding action regarding the value sent.
How to name a method that does getting and removal from the collection?
Say we have a collection Fruits. To get apples we would do something like apples = Fruits.Get("apples"). To remove - Fruits.Remove("apples"). If we want to do both in one method it would return apples and remove them form the collection. Something like apples = Fruits.Take("apples"). Any better ideas than "Take"?
Either remove() or take() are fine.
For example:
In java.util.Map, the remove() method gets and removes an object specified by a key.
In JavaSpaces, the take*() methods get and remove and object specified by a template.
pop(index) seems a reasonable misuse of stack's method to me.
Somewhat language specific but something like:
Object remove(int index)