WPF DataGrid: DataGridComboxBox ItemsSource Привязка к коллекции коллекций - PullRequest
11 голосов
/ 28 октября 2009

Положение:

Я создал DataGrid в XAML, и ItemsSource привязан к ObservableCollection определенного класса, который содержит свойства. Затем в C # я создаю DataGridTextColumn и DataGridComboBoxColumn и связываю их со свойствами объектов внутри ObservableCollection. Я могу связать DataGridComboBoxColumn с простой коллекцией, но я хочу связать его с коллекцией коллекций строк, чтобы для каждой строки ComboBox внутри DataGrid имел свою коллекцию строк. Я не смог сделать это ...

Вопрос:

Как связать 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_
};
//...

Любая помощь будет принята с благодарностью!

Примечания:

Хорошо, после прочтения двух первых ответов я кое-что заметил. Мое связывание действительно не правильно! Теперь я хочу сделать нечто похожее на то, что предложил 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 »."

Как можно связать ItemSource с данными?

Ответы [ 5 ]

11 голосов
/ 05 февраля 2010

Во-первых, это должно быть легко ... во-вторых, почему вы строите (и привязываете) столбцы в C #? Ик.

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

4 голосов
/ 28 октября 2009

Я думаю, что ошибка в том, как вы сделали свою привязку. Когда вы определяете столбец, привязка связана с объектом, который представлен определенной строкой. Итак, насколько я понимаю, у вас есть StatsOperation для каждой строки, поэтому столбец TextBox привязан к операции, как и у вас, а столбец ComboBox ItemsSource должен быть привязан к коллекции. Прямо сейчас это выглядит так, как будто оно связано с 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. Удачи!

2 голосов
/ 04 февраля 2010

Чтобы исправить ошибку Связывания Источника Предметов, используйте форму:

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

Вы, очевидно, не можете сделать это в инициализаторе, поэтому вам придется немного переместить свои объявления, но это должно устранить эту ошибку в вашем обновлении.

1 голос
/ 28 октября 2009

РЕДАКТИРОВАТЬ Извините, я немного медленный в полдень :). Вот обновленный ответ. Похоже, отличная статья от Винсента Сибала WPF DataGrid - DataGridComboBoxColumn v1 Intro отвечает на ваш вопрос. Есть ли это?

0 голосов
/ 06 февраля 2010

Частично - я думаю, что в том, что вы говорите, есть путаница. Вы сказали, что вам нужна коллекция наборов строк в каждой строке, чтобы в комбинированном окне могли отображаться разные строки для разных строк. Однако, чтобы в комбинированном окне отображался набор строк, вам нужен только набор строк в каждой строке, а не набор строк.

Теперь, так как вам нужен набор строк для каждой строки, вы можете подумать, что вам понадобится коллекция наборов строк.

Правильно ли я понимаю ваш вопрос? Если так, то ваше упоминание о коллекции строк неверно.

Что вам действительно нужно, так это коллекция StatOperations, в которой каждая StatOperation должна иметь коллекцию строк. Это именно то, что вы делали, как показано в ваших классах выше.

Чтобы добиться прогресса, я предлагаю вам отредактировать свой вопрос и указать, где именно вы застряли после исправления привязки, как предложено AndyG.

...