在WPF中绑定到属性指定的数组元素

时间:2010-11-04 19:51:56

标签: wpf data-binding xaml

假设我的UI上有一些TextBlocks,就像这样:

<StackPanel Orientation="Vertical">
    <TextBlock Text="{Binding DessertIndex}" />
    <TextBlock Text="{Binding Food[2]}" />
    <TextBlock Text="{Binding Food[{Binding DessertIndex}]}" />
</StackPanel>

在我的代码后面,我有类似的东西:

public partial class MainWindow : Window
{
    public int DessertIndex
    {
        get { return 2; }
    }

    public object[] Food
    {
        get
        {
            return new object[]{"liver", "spam", "cake", "garlic" };
        }
    }

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }
}

前两个TextBlocks对我来说很好,分别显示2和'cake'。第三个没有完成我想要的,即使用DessertIndex属性索引到该数组并显示'cake'。我在这里搜索了一些关于类似问题但没有找到的问题。最终,我不想在我的.xaml文件中指定像2这样的值,而是希望依赖属性来索引到该数组中。这可能吗?如果是这样,我在这里做错了什么?


编辑:

所以我更接近的是数据是这些object []的List的情况,我使用上面的StackPanel作为ListBox的DataTemplate的一部分。因此,正如Mark Heath在下面所建议的那样,使用取消引用数组的属性的想法似乎并不像我想要的那样工作。想法?

3 个答案:

答案 0 :(得分:29)

另一种方法是将MultiBinding与转换器一起使用:

<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>

然后在代码隐藏中,转换器定义如下:

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();
        }
    }
}

答案 1 :(得分:12)

如果您在DataContext上遇到DesertIndex属性的问题,为什么不能使用DesertIndex取消引用Food数组的属性:

public object SelectedFood
{
    get { return Food[DessertIndex]; }
}    

public int DessertIndex
{
    get { return 2; }
}

public object[] Food
{
    get
    {
        return new object[]{"liver", "spam", "cake", "garlic" };
    }
}

然后你可以直接绑定到:

<TextBlock Text="{Binding SelectedFood}" />

这实际上是“MVVM”方法:使datacontext对象具有适合绑定的属性。

答案 2 :(得分:0)

只需添加Colin Thomsen的出色回答即可。

您还可以使用C#dynamic关键字使此解决方案几乎适用于每种容器类型。甚至绑定到多维容器“ {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;
    }
}
相关问题