0

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

何らかの理由で、AllPlayers関数が最初の39行に対して呼び出され、次にデータが以前に作成されたリストから取得されます。デバッグ情報からそれを見ることができます(39回の呼び出し後に印刷を停止します)。また、コンボボックス内のリストは一意ではありません。私はこの振る舞いの背後にある論理を理解していません。すべての行に対してAllPlayersを呼び出す必要があります。

4

3 に答える 3

0

あなたのアプローチは正しくありません..まず、データグリッドの仮想化が行われる順序を信頼すべきではありません。したがって、さまざまなリストをロードするためのカウンター ベースのアプローチが不規則に発生しています。

データグリッド行が非仮想化されると、コンボボックスが表示され、アイテム ソースが要求され、Window.AllPlayersプロパティから取得されます。counterただし、スクロールに基づいて順序がねじ込まれます。いくつかの範囲の行をスキップして突然スクロールする場合、または遅延スクロールを使用している場合は、counter常に間違っています。前後にスクロールすると、うまくいきませんcounter(カウンターを減らすコードが表示されないため)...

要するに、そのアプローチを使用しないでください。

ここで、個々のアイテムからリストをロードしたくないと言いました。変数は、counterおそらくIndexデータグリッドの現在の行を参照していItemsSourceます。もしそうなら、少なくとも同じためにマルチコンバーターを使うことができます。

コンボボックス 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;
    }
    .....
}

コードは説明のみを目的としており、コンパイルできない場合があります。

お役に立てれば。

于 2011-10-13T06:15:36.937 に答える
0

グリッドへのバインドを表示します。Players を、グリッドにバインドするコレクションのパブリック プロパティにします。39+ のリストの ctor で、そこに AllPlayers を構築します。39+ のリストがチームであり、プロパティ Name、Manager、City、Players があると仮定しましょう。テンプレートで構築されたプレーヤーを取得したとしても、それらはチームに直接関連付けられていません (ビジュアル ツリーをたどらなければ)。

于 2011-10-12T22:15:02.660 に答える
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の単なるバグだと感じています。

于 2011-10-13T08:13:09.300 に答える