WPF DataGrid: DataGridComboxBox ItemsSource привязка к коллекции коллекций
Ситуация:
Я создал DataGrid в XAML, а ItemSource привязан к ObservableCollection определенного класса, который содержит свойства. Затем в С# я создаю 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>
С#
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 ".
Как связать ItemsSource с данными?
Ответы
Ответ 1
Во-первых, это должно быть легко... во-вторых, почему вы строите (и привязываете) столбцы на С#? Ик.
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>
С#:
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
Ответ 2
Я думаю, что ошибка в том, как вы сделали свою привязку. Когда вы определяете столбец, привязка связана с объектом, который представлен определенной строкой. Так как я понимаю, у вас есть StatsOperation для каждой строки, поэтому столбец TextBox связан с операцией, как это у вас есть, и столбец ComboBox ItemsSource должен быть привязан к коллекции. Прямо сейчас это похоже на привязку к Collection<Collection<string>>
.
Я еще не определил столбцы в коде, поэтому вот пример в XAML. Я обнаружил, что ComboBoxColumn иногда бывает сложным, поэтому я показал, как вы можете иметь combobox в столбце, используя либо 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>
Я предполагаю, что операция - это выбранный элемент, данные - это элементы, которые нужно выбрать, и что ваш DataGrid привязан к коллекции StatsOperation. Удачи!
Ответ 3
Чтобы исправить ошибку привязки ItemsSource, используйте форму:
BindingOperations.SetBinding(new DataGridComboBoxColumn(), DataGridComboBoxColumn.ItemsSourceProperty, new Binding("Data"));
Вы, очевидно, не можете сделать это в intializer, поэтому вам придется немного перемещать свои объявления, но это должно позаботиться об этой ошибке в вашем обновлении.
Ответ 4
РЕДАКТИРОВАТЬ Прошу прощения, я маломерен в середине ночи:). Вот обновленный ответ. Это выглядит как отличная статья от Vincent Sibal WPF DataGrid - DataGridComboBoxColumn v1 Intro отвечает на ваш вопрос. Это?
Ответ 5
Частично - я думаю, что есть замешательство в том, что вы говорите. Вы сказали, что вам нужна коллекция коллекций строк в каждой строке, чтобы в поле со списком могли отображаться разные строки для разных строк. Однако для комбинированного блока для отображения набора строк вам потребуется только набор строк, для каждой строки, а не набор коллекций строк.
Теперь, поскольку вам нужна коллекция строк для каждой строки, вы можете подумать, что вам понадобится коллекция коллекции строк.
Правильно ли я понимаю ваш вопрос? Если это так, то неправильное упоминание о наборе строк.
В действительности вам нужна коллекция StatOperations, в которой каждый StatOperation должен иметь набор строк. Именно так вы показали, как показано в ваших классах выше.
Чтобы добиться прогресса, я предлагаю вам отредактировать свой вопрос и указать, где именно вы застряли после исправления привязки, как было предложено AndyG.