9

多次元配列内の特定の要素にリンクする 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 では区切り記号を使用でき,ないため、2 次元配列にバインドする方法がわかりません。

これ:

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

XAML はバインディング コンストラクターに 2 つの引数があると解釈されるため、コンパイルされません。パーサーをエスケープする方法はありますか、それとも私が気付いていない別の書き方がありますか?


編集:

このようにセパレーターをエスケープできることがわかりました

<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# は私の母国語にインストールされました。 "}

多次元配列をバインドすることは実際には不可能ですか?

4

2 に答える 2

8

次のように定義された MultivalueConverter を使用して、2 次元配列にバインドできます。

 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 つのパラメーター、2 次元配列と 2 つのインデックスを取得し、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 でインデックスをプロパティとして定義する方がおそらく適切です。固定値を使用して説明するだけです。

于 2015-02-05T10:44:55.790 に答える
2

デフォルトでは、WPF XAML はこのような 2D 配列へのバインディングを許可しません。1D 配列のみ。しかし、不可能なことは何もありません。時間がかかるだけです。これを行うにはカスタム クラスを作成し、それをバインディングの方法として使用する必要があります。

/// <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]}"/>

ソリューションのソース。

これはパフォーマンスに影響を与える可能性があり、そもそも多次元配列を使用することに疑問を抱くようになりますか? より簡単に実装できるリストを使用できます。このソリューションを見てください。

于 2015-02-05T00:56:00.313 に答える