Search code examples
wpfbindingindirection

Bind XAML property indirectly


Imagine, I have a button and a binding:

<Button Content="{Binding Path=FailOverStrings.ConfigTestBtn, Source={StaticResource    ResourceWrapper}}></Button>

Now I want to setup an array of such buttons:

        <Grid >
            <ItemsControl>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Button Content="{Binding Title}" />
                        </Grid>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </Grid>

I will create a collection in the code behind but how to say that 'Title' which is equal to 'ConfigTestBtn' is not really a string 'ConfigTestBtn' itself but is a name of a property of FailOverStrings ?

Some kind of an indirection in binding. I suppose I can write a converter to do it, but is it really necessary?


Solution

  • Suppose you have a class like below.

    public class FailOverStrings
    {
        public FailOverStrings()
        {
            ConfigTestBtn = "Actual value";
        }
    
        public string ConfigTestBtn { get; set; }
    }
    

    Then your converter can look like this

    public class PropertNameToValueConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string retValue = string.Empty;
            FailOverStrings settings = new FailOverStrings();
            foreach(PropertyInfo pinfo in settings.GetType().GetProperties())
            {
                if (pinfo.Name == value.ToString())
                {
                    retValue = pinfo.GetValue(settings, null).ToString();
                }
            }
            return retValue;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    And using this converter in button like this

    <Window.Resources>
        <local:PropertNameToValueConverter x:Key="PropertNameToValueConverter"></local:PropertNameToValueConverter>
    </Window.Resources>
    <Grid>
        <Button Content="{Binding ElementName=myWindow, Path=PropertyName, Converter={StaticResource ResourceKey=PropertNameToValueConverter}}" Width="100" Height="30" />
    </Grid>