WPF DataGridCell模板中的动态绑定

5
我有一个关于在WPF中绑定DataGrid的问题。我正在使用自带的DataGrid而不是Toolkit,尽管我认为它们基本相同。
我想绑定到一个数据集,该数据集有52列,每一周都有一列。因此,我想动态地绑定数据,而不是指定每个字段。每个字段的值取决于某些条件的真或假。基于这个值,如果条件成立,我想在单元格模板中显示一个图像,并在条件不成立时隐藏它。
我的问题是,我找到的所有使用模板的示例都是针对固定的、预定义的字段的情况,其中你可以使用类似Text="{Binding UserName}"的绑定。这对我没有好处,因为我不知道设计时字段的名称。
我准备了一个简化的示例展示问题。在这个示例中,生成了一个包含True和False值的数据表。我的模板中的图像从未可见过。如何根据数据中的True或False值使其不可见?
<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>

代码如下:

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

}

这是一段HTML代码,没有明确的含义。
以下是英文文本的翻译:
NB 这可能很明显,但我完全以错误的方式来解决这个问题。我要坦白:我已经试图理解WPF几个月了,但似乎我仍然总是以错误的方式来解决每个问题。希望我能很快明白。
1个回答

9
您可以使用一个MultiBinding,第一个绑定将从单元格中获取实际的数据上下文(行),第二个绑定获取列。从那里,您可以检索单元格的值。
转换器代码:
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>

我在测试中使用了一个TextBlock代替图片,但代码将保持不变。如果可以直接在DataGridCell的样式中定义,就避免为图像定义样式。


谢谢您非常迅速的回答,Julien。它完美地解决了问题。 - Richard
非常感谢,这对我帮助很大! - David

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接