Say I\'ve got some TextBlocks on my UI, something like so:
Another alternative is to use MultiBinding with a converter:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<StackPanel Orientation="Vertical">
<StackPanel.Resources>
<local:FoodIndexConverter x:Key="foodIndexConverter" />
</StackPanel.Resources>
<TextBlock Text="{Binding DessertIndex}" />
<TextBlock Text="{Binding Food[2]}" />
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource foodIndexConverter}">
<Binding Path="DessertIndex" />
<Binding Path="Food"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</Window>
Then in the code-behind, the converter is defined something like this:
namespace WpfApplication1
{
public class FoodIndexConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (values == null || values.Length != 2)
return null;
int? idx = values[0] as int?;
object[] food = values[1] as object[];
if (!idx.HasValue || food == null)
return null;
return food[idx.Value];
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Just To add on the great answer by Colin Thomsen.
You could also use C# dynamic
keyword to make this solution work with pretty much every container type. Or even bind to multidimensional containers "{Binding Food[{Binding DessertIndex1}][{Binding DessertIndex2}]}"
public class ContainerDoubleAccessConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
try
{
dynamic idx1 = values[0];
dynamic idx2 = values[1];
dynamic container = values[2];
return container[idx1][idx2];
}
catch (System.Exception err)
{
DebugTrace.Trace("bad conversion " + err.Message);
}
return null;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
if you are going to the trouble of having a DesertIndex
property on your DataContext, why not a property that dereferences the Food array with DesertIndex:
public object SelectedFood
{
get { return Food[DessertIndex]; }
}
public int DessertIndex
{
get { return 2; }
}
public object[] Food
{
get
{
return new object[]{"liver", "spam", "cake", "garlic" };
}
}
then you can bind directly to that:
<TextBlock Text="{Binding SelectedFood}" />
This is essentially the "MVVM" approach: make the datacontext object have properties that are just right for binding to.