2013-04-20 12 views
9

Mam problem z sformułowaniem ciągu XAML, który będzie łączył się z konkretnym elementem w tablicy wielowymiarowej.WPF Wiązanie do tablicy wielowymiarowej w Xaml

DataContext zawiera następujące linie:

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 zawiera następujące linie:

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

Wiązanie OneDimension i Jagged pracy, jak oczekiwano. Wiązanie z TwoDimension nie działa i wygląda na niepoprawne, jednak XAML nie pozwala mi używać separatora ,, więc nie wiem, jak powiązać z tablicą dwuwymiarową.

to:

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

nie kompiluje ponieważ XAML zostanie zinterpretowane jako posiadające dwa argumenty za wiązanie konstruktora. Czy jest jakiś sposób na ucieczkę od parsera lub czy istnieje inny sposób pisania tego, o czym nie wiem?


EDIT:

Właśnie dowiedziałem się, że jest możliwe, aby uciec separator jak ten

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

lub po prostu otoczyć argument ze znacznikami jak ten

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

Jednak ta linia prowadzi teraz do wyjątku: System.ArgumentException {"Das Array war kein eindimension ales Array. "} unfortunatelly C# instalował się w moim ojczystym języku - irytujące jak gówno ... więc to z grubsza tłumaczy się na {" The Array nie był onedimensionale Array. "}

Czy w ogóle nie można wiązać tablic wielowymiarowych?

+0

O ile mi wiadomo, nie jest możliwe wiązanie tablic wielowymiarowych w czystym 'Xaml', trzeba będzie stworzyć' IValueConverter' do wykonania pracy. –

+0

Hmmm, aby to zrobić, musiałbym znać typ ... to byłaby Array ... ale istnieje ValueConverter dla tablicy - jestem tego pewien. Czy mogę wstrzyknąć moje urządzenie? – Johannes

+0

Spróbuj tego linku. Mam nadzieję, że pomaga https://nicoschertler.wordpress.com/2014/05/22/binding-to-a-2d-array-in-wpf/ –

Odpowiedz

8

Można powiązać do tablicy dwuwymiarowej przy użyciu MultivalueConverter zdefiniowane następująco:

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

że MultiDimensionalCoverter dostać 3 parametrów, tablica Dwa dimention plus dwa indeksy i XAML będzie tak:

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

zdefiniowanie indeksów jako właściwości w VM jest prawdopodobnie bardziej odpowiednie, używam tylko ustalonej wartości do zademonstrowania.

1

Domyślnie WPF XAML nie pozwala na wiązanie z taką tablicą 2D. Tylko tablice 1D. Jednak nic nie jest niemożliwe. Tylko czasochłonne. Będziesz musiał stworzyć niestandardową klasę, aby to zrobić i użyć jej jako sposobu wiązania.

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

Następnie można wiązać XAML:

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

Source roztworu.

Może to wpłynąć na wydajność, która prowadzi mnie do pytania za pomocą wielowymiarowej tablicy na początek? Możesz użyć list, które mogą być łatwiejszą implementacją. Spójrz na this solution.