There are a couple of classes

public class A { public static A A1 = new A(); public static A A2 = new A(); public static A A3 = new A(); ... } public class B { public string this[A a] { get { return a.ToString(); /*тут может быть что угодно*/ } } } 

You must specify in the binding of the element, with a DataContext instance of class B , to the property .[A:A1] , something like this:

 <TextBlock Text="{Binding Path=.[MyEnum:A.A1]"> 

however, a binding error occurs

System.Windows.Data Error: 40: BindingExpression path error: '[]' property not found on 'object' '' B '(HashCode = 36232091)'. BindingExpression: Path =. [MyEnum: A.A1]; DataItem = 'B' (HashCode = 36232091); target element is 'TextBlock' (Name = ''); target property is 'Text' (type 'String')

but if we do

 public class B { public string this[int a] { get { return a.ToString(); } } } 

and

 <TextBlock Text="{Binding Path=.[666]"> 

then everything goes with a bang. How to make a binding to an enumerated property by the index of a static property?

    1 answer 1

    Your question is not so simple. In fact, the problem is how to get a typed value instead of MyEnum:A.A1 (this text XAML considers just a string). Simple solution with x:Static :

     Text="{Binding Path=.[{x:Static MyEnum:A.A1}]" 

    does not work: apparently, markup extensions are not recognized inside the Path argument.

    But there is an easy workaround. Since your index is a constant, then you do not need to follow its changes. So, you can simply bind through the converter.

    We write:

     public class IndexerConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value == null || value == DependencyProperty.UnsetValue) return value; // мы не знаем точный тип - значит, вызываем через рефлексию return value.GetType() .GetMethod("get_Item") // так "внутри" называется indexer .Invoke(value, new object[] { parameter }); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } 

    Now XAML:

     <Window x:Class="..." xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:MyEnum="clr-namespace:..." ...> <Window.Resources> <MyEnum:IndexerConverter x:Key="IndexerConverter"/> </Window.Resources> <TextBlock Text="{Binding Converter={StaticResource IndexerConverter}, ConverterParameter={x:Static MyEnum:A.A1}}"/> </Window> 

    An alternative solution with more tricky Path creation can be found here :

     [ContentProperty("Parameters")] public class PathConstructor : MarkupExtension { public string Path { get; set; } public IList Parameters { get; set; } public PathConstructor() { Parameters = new List<object>(); } public PathConstructor(string path, object p0) { Path = path; Parameters = new[] { p0 }; } public override object ProvideValue(IServiceProvider serviceProvider) { return new PropertyPath(Path, Parameters.Cast<object>().ToArray()); } } 

    and XAML:

     <TextBlock Text="{Binding Path={MyEnum:PathConstructor [(0)], {x:Static MyEnum:A.A1}}}"/> 
    • Well, with converters I have done (albeit a multi-converter). Just not very readable. But your version looks pretty. - Dmitry Chistik
    • @Dmitry Chistik: You will need a MyEnum:A.A1 if MyEnum:A.A1 actually a variable (for example, from another Binding 'a, or some property), and not a constant. - VladD
    • @Dmitry Chistik: Found another solution, added an answer. Looks sleeker. - VladD