【问题标题】:WPF Binding to multidimensional array in the xamlWPF绑定到xaml中的多维数组
【发布时间】:2013-04-13 16:58:48
【问题描述】:

我无法制定 XAML 字符串以链接到多维数组中的特定元素。

DataContext 包含以下几行:

    private String[] _OneDimension = { "[0]", "[1]" };
    private String[][] _Jagged = { new String[] { "[0,0]", "[0,1]" }, new String[] { "[1,0]", "[1,1]" } };
    private String[,] _TwoDimension = { { "[0,0]", "[0,1]" }, { "[1,0]", "[1,1]" } };

    public String[] OneDimension { get { return _OneDimension; } }
    public String[][] Jagged { get { return _Jagged; } }
    public String[,] TwoDimension { get { return _TwoDimension; } }

XAML 包含以下几行:

    <StackPanel>
        <Button Content="{Binding OneDimension[1]}" Width="100" Height="50" />
        <Button Content="{Binding Jagged[1][1]}" Width="100" Height="50" />
        <Button Content="{Binding TwoDimension[1][1]}" Width="100" Height="50" />
    </StackPanel>

OneDimensionJagged 的绑定按预期工作。绑定到TwoDimension 不起作用并且似乎是错误的,但是 XAML 不允许我使用分隔符 , 所以我不知道如何绑定到二维数组。

这个:

        <Button Content="{Binding TwoDimension[1,1]}" Width="100" Height="50" />

无法编译,因为 XAML 被解释为具有两个用于绑定构造函数的参数。有什么方法可以逃避解析器,还是有另一种我不知道的写法?


编辑:

我刚刚发现可以像这样转义分隔符

<Button Content="{Binding TwoDimension[1\,1]}" Width="100" Height="50" />

或者只是用这样的标记围绕参数

<Button Content="{Binding 'TwoDimension[1,1]'}" Width="100" Height="50" />

然而,这行代码现在导致了一个异常:System.ArgumentException {"Das Array war kein eindimensionales Array."} 不幸的是,C# 以我的母语安装了自己 - 令人讨厌...所以这大致翻译为 {"The Array不是一维数组。"}

真的不能绑定多维数组吗?

【问题讨论】:

  • 据我所知,在纯Xaml 中绑定多维数组是不可能的,您必须创建一个IValueConverter 才能完成这项工作。
  • 嗯,要做到这一点,我必须知道类型......那将是数组......但数组有一个 ValueConverter - 我很确定。我可以注射我的 onw 吗?
  • 试试这个链接。希望对你有帮助nicoschertler.wordpress.com/2014/05/22/…

标签: wpf data-binding binding


【解决方案1】:

您可以使用这样定义的 MultivalueConverter 绑定到二维数组:

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

MultiDimensionalCoverter 得到 3 个参数,二维数组加上两个索引,Xaml 将是这样的:

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

将索引定义为 VM 中的属性可能更合适,我仅使用固定值进行演示。

【讨论】:

    【解决方案2】:

    默认情况下,WPF XAML 不允许像这样绑定到二维数组。只有一维数组。然而,没有什么是不可能的。只是费时。您必须创建一个自定义类才能执行此操作并将其用作一种绑定方式。

    /// <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;
        }
    }
    

    然后你可以绑定到 XAML:

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

    Source 的解决方案。

    这可能会影响性能,这导致我开始质疑使用多维数组?您可以使用可能更容易实现的列表。看看this solution

    【讨论】:

      猜你喜欢
      • 2015-09-15
      • 1970-01-01
      • 2012-02-22
      • 1970-01-01
      • 2011-07-06
      • 1970-01-01
      • 1970-01-01
      • 2011-08-17
      • 1970-01-01
      相关资源
      最近更新 更多