2010-01-29 46 views
5

Tôi có một câu hỏi về ràng buộc dữ liệu DataGrid trong WPF. Tôi đang sử dụng VS 2010 Beta 2 có DataGrid riêng của mình, không phải là bộ công cụ, mặc dù tôi nghĩ nó khá giống nhau.Binding động trong WPF DataGridCell Template

Tôi muốn liên kết với tập dữ liệu có 52 cột, một cột cho mỗi tuần trong năm. Vì lý do này, tôi muốn ràng buộc dữ liệu động hơn là chỉ định từng trường. Giá trị cho mỗi trường là đúng hoặc sai tùy thuộc vào một số điều kiện. Dựa trên giá trị này, tôi muốn hiển thị một hình ảnh trong mẫu ô nếu điều kiện là đúng và ẩn nó nếu điều kiện không đúng.

Vấn đề của tôi là tất cả các ví dụ về việc sử dụng các mẫu mà tôi đã tìm thấy là trường hợp của các trường được xác định trước, nơi bạn có thể có một ràng buộc như Text = "{Binding UserName}". Điều này không tốt với tôi bởi vì tôi không biết tên trường sẽ là gì vào thời gian thiết kế.

Tôi đã tạo một ví dụ đơn giản minh họa sự cố. Trong ví dụ này, một bảng dữ liệu được tạo ra chứa các giá trị true và false. Hình ảnh trong mẫu của tôi không bao giờ hiển thị. Làm thế nào tôi sẽ làm cho nó vô hình tùy thuộc vào giá trị đúng hay sai trong dữ liệu?

<Window.Resources> 

    <!--This is the bit that doesn't work...--> 
    <Style TargetType="{x:Type Image}" x:Key="HideWhenFalse"> 
     <Setter Property="Visibility" Value="Hidden" /> 
     <Style.Triggers> 
      <DataTrigger 
     Binding="{Binding Path=???}" 
     Value="True"> <!--What to put for the path? --> 
       <Setter Property="Visibility"> 
        <Setter.Value> 
         Visible 
        </Setter.Value> 
       </Setter> 
      </DataTrigger> 
     </Style.Triggers> 
    </Style> 
    <!--Up to here--> 

    <Style x:Key="{x:Type DataGridCell}" TargetType="{x:Type DataGridCell}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate> 
        <StackPanel> 
         <Image Source="Images/tick.bmp" Style="{StaticResource HideWhenFalse}"> 

         </Image> 
        </StackPanel> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</Window.Resources> 

<Grid> 
    <DataGrid 
     x:Name="myDataGrid" 
     AutoGenerateColumns="True" > 

    </DataGrid> 
</Grid> 

Mã đằng sau:

public partial class MainWindow: Window {

public MainWindow() 
{ 
    InitializeComponent(); 

    DataTable dtTable = new DataTable(); 

    dtTable.Columns.Add("A", typeof(Boolean)); 
    dtTable.Columns.Add("B", typeof(Boolean)); 
    dtTable.Columns.Add("C", typeof(Boolean)); 
    dtTable.Columns.Add("D", typeof(Boolean)); 
    dtTable.Columns.Add("E", typeof(Boolean)); 
    dtTable.Columns.Add("F", typeof(Boolean)); 

    for (int i = 0; i < 5; i++) 
    { 
     object[] oValues = new Object[dtTable.Columns.Count]; 

     for (int j = 0; j < dtTable.Columns.Count; j++) 
     { 
      oValues[j] = (j % 2 == 1) ? true : false; 
     } 

     dtTable.Rows.Add(oValues); 
    } 

    myDataGrid.ItemsSource = dtTable.DefaultView; 
    myDataGrid.Items.Refresh(); 
} 

}

NB Điều này có lẽ là hiển nhiên và tôi đang tiếp cận vấn đề một cách hoàn toàn sai. Đây là một lời thú nhận: Tôi đã cố gắng để có được đầu của tôi xung quanh WPF cho một vài tháng nay và tôi vẫn dường như tìm thấy bản thân mình tiếp cận MỌI vấn đề một cách sai lầm. Tôi hy vọng đồng xu giảm sớm.

Trả lời

9

Bạn có thể sử dụng MultiBinding, với ràng buộc đầu tiên lấy ngữ cảnh dữ liệu thực tế từ ô (có thể là hàng) và cột thứ hai lấy cột. Từ đó, bạn có thể truy xuất giá trị ô.

đang chuyển đổi:

public class RowColumnToCellConverter : IMultiValueConverter { 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { 
     DataRowView row = values[0] as DataRowView; 
     DataGridColumn column = values[1] as DataGridColumn; 
     return row != null && column != null 
      ? row[column.SortMemberPath] 
      : DependencyProperty.UnsetValue; 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { 
     throw new NotSupportedException(); 
    } 
} 

XAML:

<Style x:Key="{x:Type DataGridCell}" TargetType="{x:Type DataGridCell}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate> 
        <StackPanel> 
         <TextBlock x:Name="TextOK" Text="OK" Visibility="Collapsed" /> 
        </StackPanel> 
        <ControlTemplate.Triggers> 
         <DataTrigger Value="True"> 
          <DataTrigger.Binding> 
           <MultiBinding Converter="{StaticResource RowColumnToCellConverter}"> 
            <Binding /> 
            <Binding RelativeSource="{x:Static RelativeSource.Self}" Path="Column" /> 
           </MultiBinding> 
          </DataTrigger.Binding> 
          <Setter TargetName="TextOK" Property="Visibility" Value="Visible" /> 
         </DataTrigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

tôi đã sử dụng một TextBlock thay vì một hình ảnh để thử nghiệm, nhưng mã sẽ giống nhau. Chỉ cần tránh xác định kiểu cho hình ảnh nếu có thể thực hiện trực tiếp theo kiểu của DataGridCell.

+0

Cảm ơn câu trả lời rất nhanh của bạn, Julien. Nó hoạt động một điều trị. – Richard

+1

@Richard - bạn nên chấp nhận câu trả lời này – David

+0

merci bien, ça m'a beaucoup aidé! – David