2010-11-04 22 views
25

Nói rằng tôi đã có một số TextBlocks trên giao diện người dùng của tôi, một cái gì đó giống như vậy:Binding trong WPF để phần tử của mảng được xác định bởi tài sản

<StackPanel Orientation="Vertical"> 
    <TextBlock Text="{Binding DessertIndex}" /> 
    <TextBlock Text="{Binding Food[2]}" /> 
    <TextBlock Text="{Binding Food[{Binding DessertIndex}]}" /> 
</StackPanel> 

và trong mã của tôi đằng sau tôi đã có một cái gì đó như thế này:

public partial class MainWindow : Window 
{ 
    public int DessertIndex 
    { 
     get { return 2; } 
    } 

    public object[] Food 
    { 
     get 
     { 
      return new object[]{"liver", "spam", "cake", "garlic" }; 
     } 
    } 

    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = this; 
    } 
} 

Hai TextBlocks đầu tiên hiển thị tốt cho tôi, hiển thị 2 và 'bánh' tương ứng. Điều thứ ba không thực hiện được những gì tôi muốn, cụ thể là sử dụng thuộc tính DessertIndex để chỉ mục vào mảng đó và cũng hiển thị 'bánh'. Tôi đã làm một chút tìm kiếm ở đây trên SO cho một câu hỏi tương tự nhưng không tìm thấy một. Cuối cùng, tôi không muốn chỉ định các giá trị như 2 trong tệp .xaml của tôi và muốn dựa vào thuộc tính thay vì để lập chỉ mục vào mảng đó. Điều này có thể không? Nếu vậy, tôi đang làm gì sai ở đây?


EDIT:

Vì vậy, những gì tôi chặt chẽ hơn có là một tình huống mà các dữ liệu là một danh sách các đối tượng [] và tôi đang sử dụng trên StackPanel như một phần của một DataTemplate cho một ListBox. Vì vậy, ý tưởng, như Mark Heath cho thấy dưới đây, sử dụng một tài sản mà dereferences mảng dường như không hoạt động như tôi muốn. Ý tưởng?

Trả lời

26

Một lựa chọn khác là sử dụng MultiBinding với bộ chuyển đổi:

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:WpfApplication1" 
     Title="MainWindow" Height="350" Width="525"> 
    <StackPanel Orientation="Vertical"> 
     <StackPanel.Resources> 
      <local:FoodIndexConverter x:Key="foodIndexConverter" /> 
     </StackPanel.Resources> 
     <TextBlock Text="{Binding DessertIndex}" /> 
     <TextBlock Text="{Binding Food[2]}" /> 
     <TextBlock> 
       <TextBlock.Text> 
        <MultiBinding Converter="{StaticResource foodIndexConverter}"> 
         <Binding Path="DessertIndex" /> 
         <Binding Path="Food"/> 
        </MultiBinding> 
       </TextBlock.Text> 
     </TextBlock> 
    </StackPanel> 
</Window> 

Sau đó, trong một cái gì đó mã phía sau, bộ chuyển đổi được định nghĩa như thế này:

namespace WpfApplication1 
{ 
    public class FoodIndexConverter : IMultiValueConverter 
    { 
     public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      if (values == null || values.Length != 2) 
       return null; 

      int? idx = values[0] as int?; 
      object[] food = values[1] as object[]; 

      if (!idx.HasValue || food == null) 
       return null; 

      return food[idx.Value]; 
     } 

     public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 
+0

Cảm ơn Colin - điều này hoạt động rất tốt cho ứng dụng thử nghiệm của tôi và nghi ngờ nó sẽ hoạt động tốt trong thực tế. Đó là một ngày tốt lành - tôi đã học được điều gì đó thực sự thú vị từ bạn. :) – itsmatt

+2

Bạn có thể bị cám dỗ để thử một cái gì đó khác nhau bằng cách sử dụng một ConverterParameter để tránh multibinding. Thật không may, điều đó sẽ dẫn đến hư không, vì ConverterParameter không thể sử dụng một ràng buộc vì nó không phải là DependencyProperty và bạn phải sử dụng MultiBinding –

10

nếu bạn đang đi đến những rắc rối của việc có một tài sản DesertIndex trên DataContext của bạn, tại sao không phải là một tài sản đó dereferences mảng thực phẩm với DesertIndex:

public object SelectedFood 
{ 
    get { return Food[DessertIndex]; } 
}  

public int DessertIndex 
{ 
    get { return 2; } 
} 

public object[] Food 
{ 
    get 
    { 
     return new object[]{"liver", "spam", "cake", "garlic" }; 
    } 
} 

sau đó bạn có thể liên kết trực tiếp đến rằng:

<TextBlock Text="{Binding SelectedFood}" /> 

Đây thực chất là phương pháp "MVVM": làm cho đối tượng datacontext có các thuộc tính phù hợp để gắn kết.

+0

Mark, nhờ trả lời của bạn. Xem bản chỉnh sửa của tôi cho câu hỏi gốc để biết thêm chi tiết. Về cơ bản tôi đang đối phó với một ListBox và một danh sách các đối tượng này [] vì vậy tôi không biết làm thế nào để thực hiện các dereferencing như bạn đề nghị làm việc trong bối cảnh này. Dữ liệu không phải của tôi và tôi đã phải đối phó với nó như nó được. Ý tưởng? – itsmatt

+0

vâng tôi đã tự hỏi liệu đó có phải là trường hợp không. –

Các vấn đề liên quan