peterh
Topic Author
Posts: 21
Joined: 13 Mar 2015, 13:50

Issue when using custom class with indexes in data binding

14 Apr 2015, 15:07

I have in my application (Unity) a class for testing indexing in DataBindings in XAML:
    public class IndexTest 
    {
        public IndexTest() 
		{
			_list.Add("foobar");
			_dict.Add("foo", "bar");
		}
		
        private List<string> _list = new List<string>();
        private Dictionary<string, string> _dict = new Dictionary<string, string>();
        private Lexicon _lex = new Lexicon();

        public List<string> List { get { return _list; } }
        public Dictionary<string, string> Dict { get { return _dict;  } }
        public Lexicon Lex { get { return _lex; } }

        //Custom class with indexer.
        public class Lexicon 
	    {
		    public string this[string arg] 
		    {
                get 
                {
                    var str = "foo " + arg;
                    return str; 
                }
		    }
	    }
    }
That is used as a DataContext for a XAML with the contents:
<StackPanel>
		<TextBlock Text="{Binding List[0]}"/>
		<TextBlock Text="{Binding Dict[foo]}"/>
		<TextBlock Text="{Binding Lex[foo]}"/> 
	</StackPanel>
When I run this as a WPF-application in Blend, all three TextBlock behave as expected:
Image
Using Noesis+Unity, however, the final TextBlock (the one using my custom indexer) ends up empty. How come? Am I missing something?
 
User avatar
sfernandez
Site Admin
Posts: 1912
Joined: 22 Dec 2011, 19:20

Re: Issue when using custom class with indexes in data bindi

14 Apr 2015, 15:52

Currently we only support indexers on classes that implement the IList or IDictionary interface.
You will have to implement the IDictionary interface on your Lexicon class meanwhile.

You can create a ticket in our bugtracker if you need this feature to be implemented.
 
peterh
Topic Author
Posts: 21
Joined: 13 Mar 2015, 13:50

Re: Issue when using custom class with indexes in data bindi

15 Apr 2015, 14:47

Implementing IDictionary would not be a problem, but I have a hard time getting that to work as well. Are there any specific parts of the interface that need to be implemented for it to work?

I have only implemented the indexer (the rest of the members just throw exceptions when accessed).
 
User avatar
sfernandez
Site Admin
Posts: 1912
Joined: 22 Dec 2011, 19:20

Re: Issue when using custom class with indexes in data bindi

17 Apr 2015, 19:33

You also have to implement IDictionary.Contains() because we use it when trying to solve the binding.

Anyway, we have to improve our code to support simple indexer properties. Please add this feature to the bugtracker to follow the status of the implementation.
 
peterh
Topic Author
Posts: 21
Joined: 13 Mar 2015, 13:50

Re: Issue when using custom class with indexes in data bindi

23 Apr 2015, 11:13

I have now implemented IDictionary, with implementations for IDictionary.Contains(), IDictionary.this[], IDictionary.ContainsKey(). I still can't access the indexes through data bindings. In fact, it seems none of the methods or properties from IDictionary are ever accessed. Any idea?

The Lexicon class looks as follows:
//NotifyPropertyChangedBase is simply an implementation of INotifyPropertyChanged
public class Lexicon : NotifyPropertyChangedBase, IDictionary<string, string>
{

    //This is the backend class I am writing a wapper for.
    private LanguageManager _mgr { get { return LanguageManager.Instance; } }
	
	public SmartCultureInfo Culture 
	{
		set 
        {
            Debug.Log("New culture: " + value.nativeName);
            _mgr.ChangeLanguage(value);
            NotifyPropertyChanged("Item[]");
        }
		get 
        {
            var mgr = _mgr;
            return mgr.GetCultureInfo(mgr.LoadedLanguage);
        }
	}

    public List<SmartCultureInfo> Languages
    {
        get { return _mgr.GetSupportedLanguages(); }
    }

    #region IDictionary
    public bool ContainsKey(string key)
    {
        var found = _mgr.HasKey(key);
        Debug.Log("Looking for key: " + key + " found: " + found );
        return found;
    }

    public string this[string key]
    {
        get
        {
            Debug.Log("Fetch key: " + key);
            return _mgr.GetTextValue(key);
        }
        set
        {
            Debug.Log("Calling set on indexer for key: " + key);
            throw new System.NotSupportedException();
        }
    }

    public bool Contains(KeyValuePair<string, string> item)
    {
        Debug.Log("Contains?");
        var val = _mgr.GetTextValue(item.Key);
        var contains = item.Value.Equals(val);
        return contains;
    }
    
    #endregion

    #region Not supported features

    

    public bool TryGetValue(string key, out string value)
    {
        Debug.Log("Called TryGetValue");
        throw new System.NotSupportedException();
    }

    public ICollection<string> Values
    {

        get { Debug.Log("Called Values"); throw new System.NotSupportedException(); }
    }

    public void Add(string key, string value)
    {
        Debug.Log("Called Add");
        throw new System.NotSupportedException();
    }
    public bool Remove(string key)
    {
        Debug.Log("Called Remove");
        throw new System.NotSupportedException();
    }
    public ICollection<string> Keys
    {
        get { Debug.Log("Called Keys"); throw new System.NotSupportedException(); }
    }
    public System.Collections.IEnumerator GetEnumerator()
    {
        Debug.Log("Called GetEnumerator");
        throw new System.NotSupportedException();
    }

    public void Add(KeyValuePair<string, string> item)
    {
        Debug.Log("Called Add");
        throw new System.NotSupportedException();
    }

    public void Clear()
    {
        Debug.Log("Called Clear");
        throw new System.NotSupportedException();
    }
    public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex)
    {
        Debug.Log("Called CopyTo");
        throw new System.NotSupportedException();
    }

    public int Count
    {
        get { Debug.Log("Called Count"); throw new System.NotSupportedException(); }
    }

    public bool IsReadOnly
    {
        get { Debug.Log("Called IsReadOnly"); throw new System.NotSupportedException(); }
    }

    public bool Remove(KeyValuePair<string, string> item)
    {
        Debug.Log("Called Remove");
        throw new System.NotSupportedException();
    }

    IEnumerator<KeyValuePair<string, string>> IEnumerable<KeyValuePair<string, string>>.GetEnumerator()
    {
        Debug.Log("Called GetEnumerator2");
        throw new System.NotSupportedException();
    }

    #endregion

}
in the (simplified) XAML:
<TextBlock Text="{Binding Lex[LeftBox]}"/>
<TextBlock Text="{Binding Lex[RightBox]}"/>
<ComboBox ItemsSource="{Binding Lex.Languages}" SelectedItem="{Binding Lex.Culture}"/>

I have filed a ticket requesting proper support for custom indexers in data bindings.
 
User avatar
sfernandez
Site Admin
Posts: 1912
Joined: 22 Dec 2011, 19:20

Re: Issue when using custom class with indexes in data bindi

23 Apr 2015, 20:43

Ok, we will follow the status of this feature in the bugtracker.
Thanks for your collaboration.

Who is online

Users browsing this forum: Google [Bot] and 1 guest