11

状況:

XAML で DataGrid を作成しました。ItemsSource は、プロパティを含む特定のクラスの ObservableCollection にバインドされています。次に、C# で DataGridTextColumn と DataGridComboBoxColumn を作成し、これらを ObservableCollection 内のオブジェクトのプロパティにバインドします。DataGridComboBoxColumn を単純なコレクションにバインドできますが、それを文字列のコレクションのコレクションにバインドして、行ごとに DataGrid 内の ComboBox が異なる文字列のコレクションを持つようにします。私はそうするのに失敗しました...

質問:

このタイプの列の行ごとに異なる文字列のコレクションを持つことができるように、DataGridCombBoxColumn をバインドするにはどうすればよいですか?

コードサンプル:

XAML:

<Window>
  <!-- ... -->
  WPFToolkit:DataGrid
           x:Name="DG_Operations"
           Margin="10,5,10,5" 
           Height="100" 
           HorizontalAlignment="Stretch" 
           FontWeight="Normal" 
           ItemsSource="{Binding Path=OperationsStats}"
           AlternatingRowBackground="{DynamicResource SpecialColor}" 
           HorizontalScrollBarVisibility="Auto" 
           VerticalScrollBarVisibility="Visible" 
           SelectionMode="Extended"
           CanUserAddRows="False" 
           CanUserDeleteRows="False"
           CanUserResizeRows="True" 
           CanUserSortColumns="True"
           AutoGenerateColumns="False" 
           IsReadOnly="False" 
           IsEnabled="True"
           BorderThickness="1,1,1,1" 
           VerticalAlignment="Stretch"/>
  <!-- ... -->
</Window>

C#:

public class DataModelStatsOperations
{
   public ObservableCollection<IStatsOperation> OperationsStats { get; set; }
}

public interface IStatsOperation
{
   string Operation { get; set; }
   Collection<string> Data{ get; set; }
}

public class StatsOperation : IStatsOperation
{
    public StatsOperation(string operation, Collection<string> data)
    {
        Operation = operation;
        Data = data;
    }
    public string Operation { get; set; }
    public Collection<string> Data{ get; set; }
}

private ObservableCollection<IStatsOperation> dataOperations_ =
        new ObservableCollection<IStatsOperation>();

//...
 Binding items = new Binding();
 PropertyPath path = new PropertyPath("Operation");
 items.Path = path;
 DG_Operations.Columns.Add(new DataGridTextColumn()
 {
     Header = "Operations",
     Width = 133,
     Binding = items
  });
  DG_Operations.Columns.Add(new DataGridComboBoxColumn()
  {
     Header = "Data",
     Width = 190,
     ItemsSource = /*???*/,
     SelectedValueBinding = new Binding("Data"),
     TextBinding = new Binding("Data")
  });
dataOperations_.Add(new StatsOperation(CB_Operation.SelectedItem.ToString(),
                                                           dataCollection));
DG_Operations.DataContext = new DataModelStatsOperations
{
    OperationsStats = dataOperations_
};
//...

どんな助けでも大歓迎です!

ノート:

さて、最初の2つの回答を読んだ後、私は何かに気づきました. 私のバインディングは本当に正しくありません! 今、私がやりたいことは、AndyG が提案したものに似たものです。

DG_Operations.Columns.Add(new DataGridComboBoxColumn()
{
    Header = "Data",
    Width = 190,
    ItemsSource = new Binding("Data"), //notice this here does not work (have a look at the following error)
    SelectedValueBinding = new Binding("Operation"),
    TextBinding = new Binding("Operation")
});

エラー:「型 'System.Windows.Data.Binding' を 'System.Collections.IEnumerable' に暗黙的に変換できません。」

ItemsSource をデータにバインドするにはどうすればよいですか?

4

6 に答える 6

11

まず、これは簡単なはずです...次に、なぜC#で列を作成(およびバインド)するのですか?Eek。

XAML(怠惰なため、通常のグリッドを使用しています):

<ListView Name="MyListView">
    <ListView.View>
        <GridView>

            <GridView.Columns>

                <GridViewColumn DisplayMemberBinding="{Binding Operation}" />

                <GridViewColumn>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding Choices}" />
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>

            </GridView.Columns>

        </GridView>
    </ListView.View>
</ListView>

C#

void Window1_Loaded(object sender, RoutedEventArgs e)
{
    var dahList = new List<StatsOperation>();

    dahList.Add(new StatsOperation
    {
        Operation = "Op A",
        Choices = new string[] { "One", "Two", "Three" },
    });

    dahList.Add(new StatsOperation
    {
        Operation = "Op B",
        Choices = new string[] { "4", "5", "6" },
    });

    this.MyListView.ItemsSource = dahList;
}

結果:

動的コンボボックスを選択できるWPFグリッドhttp://www.singingeels.com/Articles/Articles/UserImage.aspx?ImageID=b1e3f880-c278-4d2b-bcc2-8ad390591200

于 2010-02-04T22:12:20.547 に答える
5

間違いは、バインディングのやり方にあると思います。列を定義すると、バインディングは特定の行によって表されるオブジェクトに関連付けられます。私が理解しているように、行ごとに StatsOperation があるため、TextBox 列は操作にバインドされ、ComboBox 列の ItemsSource は Collection にバインドする必要があります。現在、 にバインドされているようCollection<Collection<string>>です。

コード ビハインドで列を定義したことがないので、XAML の例を次に示します。ComboBoxColumn は扱いにくい場合があるので、TemplateColumn または ComboBoxColumn を使用して列にコンボボックスを配置する方法を示しました。私は自分のコードからコピーして貼り付けたので、あなたの場合は「dg」を「WPFToolkit」に置き換えてください:

<dg:DataGrid
      ...
      ...>
      <dg:DataGrid.Columns>
            <dg:DataGridTextColumn Binding="{Binding Operation}" CanUserReorder="True" CanUserResize="True" Header="Operation" />
            <dg:DataGridTemplateColumn CanUserReorder="True" CanUserResize="True" Header="Template Column">
                <dg:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox ItemsSource="{Binding Data}" SelectedItem="{Binding Operation}" />
                    </DataTemplate>
                </dg:DataGridTemplateColumn.CellTemplate>
            </dg:DataGridTemplateColumn>
            <dg:DataGridComboBoxColumn
                Header="ComboBox Column"                                                                                    
                 SelectedValueBinding="{Binding Operation}"                     
                 SelectedItemBinding="{Binding Operation}">
                <dg:DataGridComboBoxColumn.ElementStyle>
                    <Style TargetType="ComboBox">
                        <Setter Property="IsSynchronizedWithCurrentItem" Value="False" />
                        <Setter Property="ItemsSource" Value="{Binding Data}" />
                    </Style>
                </dg:DataGridComboBoxColumn.ElementStyle>
                <dg:DataGridComboBoxColumn.EditingElementStyle>
                    <Style TargetType="ComboBox">
                        <Setter Property="ItemsSource" Value="{Binding Data}" />
                        <Setter Property="IsDropDownOpen" Value="True" />
                    </Style>
                </dg:DataGridComboBoxColumn.EditingElementStyle>
            </dg:DataGridComboBoxColumn>
      </dg:DataGrid.Columns>

</dg:DataGrid>

Operation が選択された項目で、Data が選択対象の項目であり、DataGrid が StatsOperation のコレクションにバインドされていると想定しています。幸運を!

于 2009-10-28T01:25:34.457 に答える
2

ItemsSource バインディング エラーを修正するには、次のフォームを使用します。

BindingOperations.SetBinding(new DataGridComboBoxColumn(), DataGridComboBoxColumn.ItemsSourceProperty, new Binding("Data"));

明らかにイニシャライザーでこれを行うことはできないため、宣言を少し移動する必要がありますが、更新でそのエラーを処理する必要があります。

于 2010-02-04T02:39:52.360 に答える
1

編集申し訳ありませんが、真夜中は少し遅くなります:)。これが更新された回答です。Vincent Sibal WPF DataGrid - DataGridComboBoxColumn v1 Introの素晴らしい記事があなたの質問に答えているようです。そうですか?

于 2009-10-27T21:52:55.883 に答える
0

一部 - あなたの言っていることには混乱があると思います。コンボボックスが異なる行に対して異なる文字列を表示できるように、各行に文字列のコレクションのコレクションが必要だと言いました。ただし、コンボ ボックスに一連の文字列を表示するには、文字列のコレクションのコレクションではなく、行ごとに文字列のコレクションのみが必要です。

行ごとに文字列のコレクションが必要なので、文字列のコレクションのコレクションが必要だと思うかもしれません。

あなたの質問に対する私の理解は正しいですか?もしそうなら、文字列のコレクションのコレクションについてのあなたの言及は間違っています。

実際に必要なのは、各 StatOperation に文字列のコレクションが必要な StatOperations のコレクションです。これは、上記のクラスで示したとおりです。

先に進むには、質問を編集し、AndyG の提案に従ってバインディングを修正した後、行き詰まった場所を正確に指摘することをお勧めします。

于 2010-02-06T11:07:44.693 に答える