-
Notifications
You must be signed in to change notification settings - Fork 675
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using IMap/IObservableMap as ItemsSource for ListView #1612
Comments
Collections and generics are a notoriously difficult problem with WinRT. @Holo-Krzysztof the CLR wraps (or implements, I don't remember) the collection with one that implements the IBindableIterable interface (and any other IBindable* interface). I'm fairly certain the CX projection layer does this as well, but I'd have to double check. Does your issue reproduce there as well, or is it specific to cpp/winrt? |
There's an email thread going about this with @kennykerr to try to figure out what we should do. .NET implements |
We already have an issue for this: microsoft/cppwinrt#418 The main unknown is this:
What exactly C++/WinRT should implement is the question and one that only the Xaml team can definitively answer. C++/WinRT already implements You can find the C++/WinRT implementation here. Feel free to suggest an implementation that will satisfy Xaml. |
.Net implements IEnumerable<KeyValuePair<K,V>>, which projects to WinRT as IIterable<IKeyValuePair<K,V>>. It also implements IEnumerable, which projects as IIterable. Could e.g. winrt::impl::observable_map similarly implement IIterable? It means that observable_map in this case needs to implement an adapter that's a pass-through for instance types, and does boxing for value types. |
|
Sorry, yes, I meant IIterable. Generalizing to the IIterable case, when T is an instance type the IInspectable is the T instance. When T is a value type, IInspectable is a boxed T. |
Sure, that's what we do for vectors already - box the value. The question is what to do with associative containers where there is a key and a value. How do we box the pair such that Xaml will accept it? |
@kennykerr I would imagine you are correct here in that it is |
Sure, we can do that. 👍 |
Right, the ListView doesn't have to understand the properties of the item type, the DataTemplate takes care of that. |
Forgive me for being skeptical, but if the |
One mechanism the DataTemplate has is reflection (if you're using {Binding} in a C# app). And in fact in a C# app, even if the ItemsSource isn't a C# collection, ListView runs the ItemsSource through C# to get it to reflect. So this scenario still works. The other mechanism the DataTemplate has is code gen (if your're using {x:Bind}, or optionally when using {Binding} in a C++ app). There's almost enough information for Xaml to solve this ItemsSource problem with code gen though, and solve this and another problem ... Today, you do the following to show a list of people's names: <ListView ItemsSource="{x:Bind People}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Person">
<TextBlock Text="{x:Bind Name}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView> To the reader, the x:DataType is redundant; you could figure this out by looking at the type of the People collection property (it's an IIterable<Person> or IEnumerable<Person>). The Xaml language doesn't understand this though, because the language doesn't understand ListView; ItemsSource and ItemTemplate are just two properties, there's nothing statically available to understand the connection. Potentially though the language could define some metadata to set on the ListView properties, to make that connection. Then the x:DataType wouldn't be necessary, and it could generate code to do the extraction of items from the ItemsSource. |
Here is a simple implementation that implements https://gist.github.com/kennykerr/6eace7378a1a06b5e2f21da127be102a |
Yeah, thanks for the quick response @kennykerr! |
@Holo-Krzysztof are you actually able to retrieve the key and value from the pairs within the data template? |
I just tried, and I'm not quite sure how to do that since there is no concrete type I can set on DataTemplate's If there was a way to just get the boxed value the container returns I think I could use function bindings to cast from Is there a way to tell the DataTemplate to give me an |
I'm going to reopen this issue just so that @danzil sees this discussion when he gets back. :) |
@Holo-Krzysztof there's currently no way to pass the "item" to a function binding in the same scope. Nor there is a way to pass a generic type into x:DataType. The only way to make this work is if the items in the collection you set in ItemsSource are castable to a non generic type that you can pass into x:DataType. We have a work item to add support for accessing "item" in function binding parameters and also one to allow the use of generics, although that one is more complicated. We could keep this issue to enable support for this scenario. |
Are there any plans to resolve this? |
Also posted here.
I've described the problem on StackOverflow already and also filed a docs issue before finding out that the docs are actually technically right.
To summarize, I can bind an
IVector<T>
to a ListView control just fine, but when I substitute it with anIMap<K,V>
orIObservableMap<K,V>
I get exceptions. As I've found out this is due toIMap<K,V>
not implementingIIterable<IInspectable>
which is what the ItemsSource property expects.However, it is possible to use Dictionary in C# and everything works just fine, so there must be something else happening here. Do you know how to CLR handles this and how I can accomplish this in C++?
Steps to reproduce the bug
Expected behavior
The ListView shows key-value pairs the same way as when using a Dictionary in C#
Version Info
The text was updated successfully, but these errors were encountered: