{"id":102645,"date":"2019-07-03T07:00:00","date_gmt":"2019-07-03T14:00:00","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/oldnewthing\/?p=102645"},"modified":"2019-07-03T07:04:18","modified_gmt":"2019-07-03T14:04:18","slug":"20190703-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190703-00\/?p=102645","title":{"rendered":"Why does my attempt to index a collection with the <CODE>x:Bind<\/CODE> markup extension keep telling me I have an invalid binding path due to an unexpected array indexer?"},"content":{"rendered":"<p>The documentation for <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/uwp\/xaml-platform\/x-bind-markup-exension#property-path\"> the <code>x:Bind<\/code> markup extension<\/a> notes that you can use a binding path to bind to a collection with an indexer. For example, <code>Teams[0].Players<\/code> and<\/p>\n<pre>&lt;TextBlock Text=\"{x:Bind Players['John Smith']}\" \/&gt;\r\n<\/pre>\n<p>It notes that the prerequisites for being able to index into a collection from a binding path are that the model needs to implement <code>IList&lt;T&gt;<\/code> or <code>IVector&lt;T&gt;<\/code> for numeric indexing, or <code>IDictionary&lt;string, T&gt;<\/code> or <code>IMap&lt;string, T&gt;<\/code>.<\/p>\n<p>So you try it out&#8230;<\/p>\n<pre>&lt;TextBlock Text=\"{x:Bind Teams[0].Name}\"&gt;\r\n&lt;TextBlock Text=\"{x:Bind Players['John Smith']}\" \/&gt;\r\n<\/pre>\n<p>&#8230; and you get errors.<\/p>\n<pre>WMC1110 Invalid binding path 'Teams[0]' : Unexpected array indexer\r\nWMC1110 Invalid binding path 'Players['John Smith']' : Unexpected array indexer\r\nXLS0522 Invalid index value ''John Smith''.\r\n<\/pre>\n<p>What&#8217;s going on? What&#8217;s wrong with the array indexer that made it unexpected? Why is <code>'John Smith'<\/code> an invalid index value?<\/p>\n<p>Look more closely at the list of collection interfaces that support index notation. Notable by omission are the interfaces <code>IRead\u00adOnly\u00adList&lt;T&gt;<\/code>, <code>IVector\u00adView&lt;T&gt;<\/code>, <code>IRead\u00adOnly\u00adDictionary&lt;string, T&gt;<\/code> and <code>IMap\u00adView&lt;string, T&gt;<\/code>.<\/p>\n<p>What&#8217;s actually going on is that <code>Teams<\/code> and <code>Players<\/code> are not any of the types for which the <code>x:Bind<\/code> markup extension supports indexing. The error message was saying &#8220;I wasn&#8217;t expecting an array indexer here, because the thing you are trying to apply it to is not something that can be indexed.&#8221; (<!-- Generating good error messages from code analysis tools is harder than it looks -->Writing error messages is hard.)<\/p>\n<p>The <code>Teams<\/code> and <code>Players<\/code> properties are a read-only vector and read-only dictionary, and the <code>x:Bind<\/code> markup extension supports indexing only for read-write vectors and read-write dictionaries.<\/p>\n<p>Nevermind that the binding was done in one-time mode and therefore will never attempt to write back to the vector or dictionary. The markup compiler requires that the vector and dictionary be read-write in order for you to be able to use index notation.<\/p>\n<p>You can work around this by creating helper functions.<\/p>\n<pre>class MyPage\r\n{\r\n  public IReadOnlyList&lt;Team&gt; Teams { get; private set; }\r\n  public IReadOnlyDictionary&lt;string, string&gt; Players { get; private set; }\r\n  MyPage()\r\n  {\r\n    this.InitializeComponent();\r\n  }\r\n\r\n  <span style=\"color: blue;\">string GetTeamName(int i) =&gt; Teams[i].Name;\r\n  string GetPlayer(string s) =&gt; Players[s];<\/span>\r\n}\r\n\r\n&lt;!-- xaml --&gt;\r\n&lt;TextBlock Text=\"{x:Bind <span style=\"color: blue;\">GetTeamName(0)<\/span>}\"&gt;\r\n&lt;TextBlock Text=\"{x:Bind <span style=\"color: blue;\">GetPlayer('John Smith')<\/span>}\" \/&gt;\r\n<\/pre>\n<p>Unfortunately, you cannot chain beyond a function call, so you can&#8217;t write<\/p>\n<pre>&lt;!-- code in italics is wrong --&gt;\r\n&lt;TextBlock Text=\"{x:Bind <i>GetTeam(0).Name<\/i>}\"&gt;\r\n<\/pre>\n<p><b>Bonus chatter<\/b>: If you are using one-way binding rather than one-time binding, then you need a way to signal that the result of the function call has changed. You can do that by raising a <code>PropertyChanged<\/code> event for the function name itself. This is analogous to how you raise <code>PropertyChanged<\/code> events when the value of a property changes.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Important detail stated by omission.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-102645","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Important detail stated by omission.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102645","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=102645"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102645\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=102645"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=102645"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=102645"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}