开发者

Binding-driven Indexed Property Doesn't Return

Public Class View
    Public Property Items As String() = {"One", "Two", "Three"}
    Public Property Index As Integer = 0
End Class

It's instance is set as DataContext of this XAML:

<Window>
    <StackPanel>
        <ListBox ItemsSource="{Binding Items}" SelectedIndex="{Binding Index}"/>
        <Label Content="{Binding Items[Index]}"/>
    </StackPanel>
</Window>

But this doesn't work.

<Label Content="{Binding Items[{Binding Index}]}"/>

This neither.

<L开发者_运维问答abel Content="{Binding Items[0]}"/>

This works.

Is there any solution except making extra property in view? Something directly in XAML?


I'm afraid it's not possible without some code-behind, but using reflection and dynamic, you can create a converter that can do this (it would be possible without dynamic, but more complex):

public class IndexerConverter : IValueConverter
{
    public string CollectionName { get; set; }
    public string IndexName { get; set; }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Type type = value.GetType();
        dynamic collection = type.GetProperty(CollectionName).GetValue(value, null);
        dynamic index = type.GetProperty(IndexName).GetValue(value, null);
        return collection[index];
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

Put following into resources:

<local:IndexerConverter x:Key="indexerConverter" CollectionName="Items" IndexName="Index" />

and use it like this:

<Label Content="{Binding Converter={StaticResource indexerConverter}}"/>

EDIT: The previous solution doesn't update properly when the values change, this one does:

public class IndexerConverter : IMultiValueConverter
{
    public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture)
    {
        return ((dynamic)value[0])[(dynamic)value[1]];
    }

    public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

In resources:

<local:IndexerConverter x:Key="indexerConverter"/>

Usage:

<Label>
    <MultiBinding Converter="{StaticResource indexerConverter}">
        <Binding Path="Items"/>
        <Binding Path="Index"/>
    </MultiBinding>
</Label>


What you write in the binding markup extension is assigned to the Path property by default, this property is a string so any dynamic content you refer to inside it will not be evaluated. There is no simple XAML-only method to do what you try to do.


Why don't use this:

<StackPanel>
        <ListBox Name="lsbItems" ItemsSource="{Binding Items}" SelectedIndex="{Binding Index}"/>
        <Label Content="{Binding ElementName=lsbItems, Path=SelectedItem}"/>
</StackPanel>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜