WPF Binding to multidimensional array in the xaml

后端 未结 2 1899
遥遥无期
遥遥无期 2020-12-31 16:16

I have trouble to formulate the XAML string to link to a specific element in a multidimensional array.

The DataContext contains the following lines:

         


        
相关标签:
2条回答
  • 2020-12-31 16:19

    By default WPF XAML does not allow binding to a 2D array like this. Only 1D arrays. However, nothing is impossible. Just time consuming. You will have to create a custom class in order to do this and use that as a way of binding.

    /// <summary>
    /// This class is a bindable encapsulation of a 2D array.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BindableTwoDArray<T> : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private void Notify(string property)
        {
            var pc = PropertyChanged;
            if (pc != null)
                pc(this, new PropertyChangedEventArgs(property));
        }
    
        T[,] data;
    
        public T this[int c1, int c2]
        {
            get { return data[c1, c2]; }
            set
            {
                data[c1, c2] = value;
                Notify(Binding.IndexerName);
            }
        }
    
        public string GetStringIndex(int c1, int c2)
        {
            return c1.ToString() + "-" + c2.ToString();
        }
    
        private void SplitIndex(string index, out int c1, out int c2)
        {
            var parts = index.Split('-');
            if (parts.Length != 2)
                throw new ArgumentException("The provided index is not valid");
    
            c1 = int.Parse(parts[0]);
            c2 = int.Parse(parts[1]);
        }
    
        public T this[string index]
        {
            get
            {
                int c1, c2;
                SplitIndex(index, out c1, out c2);
                return data[c1, c2]; 
            }
            set
            {
                int c1, c2;
                SplitIndex(index, out c1, out c2);
                data[c1, c2] = value;
                Notify(Binding.IndexerName);
            }
        }
    
        public BindableTwoDArray(int size1, int size2)
        {
            data = new T[size1, size2];
        }
    
        public static implicit operator T[,](BindableTwoDArray<T> a)
        {
            return a.data;
        }
    }
    

    Then you can bind to XAML:

    <TextBlock Text="{Binding MyBindableTwoDArray[2-5]}"/>
    

    Source of solution.

    This may affect performance which leads me to question using a multidimensional array to begin with? You may use lists which may be an easier implementation. Take a look at this solution.

    0 讨论(0)
  • 2020-12-31 16:29

    You can bind to a Two dimensional array using a MultivalueConverter defined like this :

     class MultiDimensionalCoverter:IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            return (values[0] as String[,])[(int) values[1], (int) values[2]];  
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    that MultiDimensionalCoverter get 3 parameters, the Two Dimention array plus the two indexes, and the Xaml will be like this :

    <Window.Resources>
            <wpfApp:MultiDimensionalCoverter x:Key="MultiDimensionalCoverter"/>
        </Window.Resources>
        <Grid>
            <StackPanel>
                <Button Content="{Binding OneDimension[1]}" Width="100" Height="50" />
                <Button Content="{Binding Jagged[1][1]}" Width="100" Height="50" />
                <Button Width="100" Height="50" >
                    <Button.Resources>
                        <system:Int32 x:Key="1">1</system:Int32>
                    </Button.Resources>
                    <Button.Content>
                        <MultiBinding Converter="{StaticResource MultiDimensionalCoverter}">
                            <Binding Path="TwoDimension"/>
                            <Binding Source="{StaticResource 1}"/>
                            <Binding Source="{StaticResource 1}"/>
                        </MultiBinding>
                    </Button.Content>
                </Button>
            </StackPanel>
        </Grid>
    

    defining the indexes as properties in your VM is probably more appropriate, i am using fixed value only to demonstrate.

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