DataGrid中的每一行都不会调用ComboBox的绑定

时间:2011-10-12 21:48:22

标签: wpf binding datagrid combobox datagridtemplatecolumn

我正在尝试在DataGridTemplateColumn中创建组合框,但它应该包含不同的值,具体取决于行。这是我的代码:

<dg:DataGridTemplateColumn x:Name ="NameColumn" Header="Player Name">
    <dg:DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ComboBox
                SelectedValue="0"
                DisplayMemberPath="FullName"
                SelectedValuePath="Id"
                ItemsSource="{Binding AllPlayers, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}}"/>
        </DataTemplate>
    </dg:DataGridTemplateColumn.CellTemplate>
</dg:DataGridTemplateColumn>

每次通话后,AllPlayers将返回不同的列表。

public List<Player> AllPlayers
{
    get 
    {
        counter = counter + 1;
        Debug.Print("getting all players " + counter);

        List<Player> lst = new List<Player>();

        for (int i=0; i < 5; i++) 
        {
            Player p = new Player();
            p.Id = counter + i;
            p.FullName = "Name " + counter + i;
            lst.Add(p);
        }

        return lst;
    }
}

由于某种原因,前39行调用AllPlayers函数,然后从先前创建的列表中获取数据。我可以从调试信息中看到它(它在39次调用后停止打印)。并且组合框中的列表也不是唯一的。我不明白这种行为背后的逻辑。我需要为每一行调用AllPlayers。

3 个答案:

答案 0 :(得分:0)

显示您对网格的绑定。我会让Players成为你绑定到网格的集合的公共属性。在39+的列表中,在那里建立AllPlayers。让我们假设你的39+名单是团队,并拥有名称,经理,城市,球员的属性。即使您获得了模板中构建的玩家,他们也不会直接与团队相关联(无需走可视树)。

答案 1 :(得分:0)

您的方法不正确..首先,您不应该信任数据网格虚拟化发生的顺序。因此,基于计数器的加载不同列表的方法不规律地发生。

当数据网格行被去虚拟化时,您的组合框变得可见并要求项目源并从Window.AllPlayers属性获取它。但counter的顺序将基于滚动而被搞砸。如果您突然滚动跳过几行范围,或者如果您使用延迟滚动,则counter将始终是错误的。如果你来回滚动counter将被搞砸(因为我没有看到任何减少计数器的代码)......

所以请不要使用这种方法。

现在你说你不想从单个项目加载列表。 counter变量可能是指数据网格Index中当前行的ItemsSource。如果是这样,你至少可以使用多转换器。

Combobox XAML:

    <ComboBox
        SelectedValue="0"
        DisplayMemberPath="FullName"
        SelectedValuePath="Id" >
        <ComboBox.ItemsSource>
            <MultiBinding Converter="{StaticResource RowWiseListConverter}">
                <!--The current row item-->
                <Binding BindsDirectlyToSource="True" /> 

                <!---The items source of the data grid.-->
                <Binding Path="ItemsSource"
                         RelativeSource="{RelativeSource
                                 AncestorType={x:Type DataGrid}}"/>
            </MultiBinding>
        </ComboBox.ItemsSource>
    </ComboBox>

多转换器代码:

public class RowWiseListConverter : IMultiValueConverter
{
    public object Convert(
            object[] values,
            Type targetType,
            object parameter,
            CultureInfo culture)
    {
        var item = values[0];
        var list = values[1] as System.Collections.IEnumerable;

        if (item != null && list != null)
        {
            var counter = list.Cast<object>().ToList().IndexOf(item);

            List<Player> lst = new List<Player>();
            for (int i = 0; i < 5; i++)
            {
                Player p = new Player();
                p.Id = counter + i;
                p.FullName = "Name " + counter + i;
                lst.Add(p);
            }

            return lst; 
        }

        return null;
    }
    .....
}

该代码仅用于说明目的,可能无法编译。

希望这有帮助。

答案 2 :(得分:0)

我没有使用计数器来计算索引,但仅用于调试目的,以计算调用函数的时间,并使用它为每个组合框创建唯一列表。我的原始代码与您提供的方法相同。这是转换器:

Public Function Convert(ByVal value() As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IMultiValueConverter.Convert
    Dim playerReportRow As MainAdminDS.PlayerReportRow = value(0).Row
    'Dim sourceList As MainAdminDS.PRSourceDataTable = SmallReportForm.GetSmallReportForm().PRSource
    Dim sourceList As MainAdminDS.PRSourceDataTable = value(1)

    Dim sourceListView As New List(Of MainAdminDS.PRSourceRow)

    Dim rand As New Random
    For i As Integer = 0 To sourceList.Count - 1
        If (sourceList(i).PRSource_Id = playerReportRow.PlayerReport_Source Or rand.Next(0, 2) = 0) Then
            sourceListView.Add(sourceList(i))
        End If
    Next

    Return sourceListView
End Function

我再次为调试目的创建唯一列表。这也不起作用!!!

我通过在Object类型的DataLayer中添加新字段找到了解决方案,并且它们未分配给任何字段。这些字段包含组合框的列表,我为每个对象单独初始化这些列表。它工作得很好。但令人困惑的是,为什么以前的方法不起作用。我觉得这只是WPF中的错误。