Binding in WPF to element of array specified by property

前端 未结 3 1237
名媛妹妹
名媛妹妹 2020-11-30 01:54

Say I\'ve got some TextBlocks on my UI, something like so:


    

        
相关标签:
3条回答
  • 2020-11-30 02:28

    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();
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-30 02:36

    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;
        }
    }
    
    0 讨论(0)
  • 2020-11-30 02:40

    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.

    0 讨论(0)
提交回复
热议问题