2013-04-20 2 views
9

다차원 배열의 특정 요소에 연결하기 위해 XAML 문자열을 공식화하는 데 어려움이 있습니다.WPF 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> 

바인딩 작업 OneDimension에와 Jagged 예상대로. TwoDimension에 대한 바인딩이 작동하지 않고 잘못된 것처럼 보입니다. 그러나 XAML에서는 구분 기호 ,을 사용할 수 없으므로 2 차원 배열에 바인딩하는 방법을 알지 못합니다.

이 다음 XAML은 바인딩 생성자에 대한 두 개의 인수를 가진 것으로 해석됩니다 때문에

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

가 컴파일되지 않습니다. 파서를 벗어날 수있는 방법이 있을까, 아니면 내가 알지 못하는 이것을 쓰는 다른 방법이 있을까요?


편집 :

난 그냥이

<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 eindimension ales Array. "} unfortunatelly C#이 제 모국어로 설치되었습니다. - 이것은 대략"{배열이 일차 배열 배열이 아니 었습니다. "}로 변환됩니다.} 다차원 배열을 바인딩하는 것은 실제로 불가능합니까?

+0

순수한'Xaml'에서 다차원 배열을 바인딩 할 수 없다는 것을 알고있는 한, 작업을 수행하기 위해'IValueConverter'를 생성해야합니다. –

+0

흠, 내가 할 수있는 타입을 알면 ... Array가 될 것입니다. 그러나 배열을위한 ValueConverter가 있습니다 - 저는 확신합니다. 내 onw을 주사 할 수 있습니까? – Johannes

+0

이 링크를 사용해보십시오. 희망이 도움이 되리라. https://nicoschertler.wordpress.com/2014/05/22/binding-to-a-2d-array-in-wpf/ –

답변

8

당신은 다음과 같이 정의 된 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의 속성으로 인덱스를 정의하는 것이 더 적절할 것입니다. 고정 값만 사용하여 시연합니다.

1

기본적으로 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]}"/> 

Source합니다.

이것은 성능에 영향을 미쳐서 다차원 배열을 사용하여 처음부터 질문하게 만듭니다. 좀 더 쉽게 구현할 수있는 목록을 사용할 수 있습니다. this solution을보십시오.