WPF Datagrid: DataGridComboxBox Itemssource-Bindung an eine Sammlung von Sammlungen
-
06-07-2019 - |
Frage
Situation:
Ich habe ein Datagrid in XAML erstellt und die Itemssource auf eine ObservableCollection einer bestimmten Klasse binded sind, die Eigenschaften enthält. Dann in C #, erstelle ich eine Datagridtextcolumn und eine DataGridComboBoxColumn und binded diese an die Eigenschaften der Objekte innerhalb des ObservableCollection. Ich kann die DataGridComboBoxColumn auf eine einfache Sammlung binden, aber was ich will zu tun ist, binden sie an eine Sammlung von Sammlungen von Strings, so dass für jede der ComboBox Zeile innerhalb der Datagrid eine andere Sammlung von String hat. Ich habe nicht zu tun ...
Frage:
Wie kann ich binde den DataGridCombBoxColumn so, dass ich eine andere Sammlung von Strings für jede Zeile dieser Art der Spalte haben kann?
Code-Beispiel:
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_
};
//...
Jede Hilfe wäre sehr geschätzt werden!
Weitere Informationen:
Okay, also nachdem die beiden ersten Antworten lesen bemerkte ich etwas. Meine Bindung ist wirklich nicht richtig! Nun, was ich tun möchte, ist etwas Ähnliches, was AndyG vorgeschlagen:
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")
});
Fehler: "Kann nicht implizit Typ 'System.Windows.Data.Binding' auf 'System.Collections.IEnumerable' konvertieren"
Wie kann die Itemssource an Daten gebunden werden?
Lösung
Zum einen sollte dies einfach sein ... zweitens, warum sind Sie bauen (und Bindung) Spalten in C #? Eek.
XAML (Ich bin ein regelmäßiges Gitter verwenden, weil ich faul bin):
<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;
}
Die Ergebnisse:
Andere Tipps
Ich denke, der Fehler in ist, wie Sie Ihre Bindung getan haben. Wenn Sie eine Spalte definieren, wird die Bindung an das Objekt beziehen, die von einer bestimmten Zeile repräsentiert wird. So wie ich es verstehe, haben Sie eine StatsOperation für jede Zeile, so dass die TextBox-Säule wird für den Betrieb gebunden, das ist, wie Sie es haben, und die ComboBox Spalte Itemssource sollte auf eine Sammlung gebunden werden. Im Moment sieht es aus wie es zu einem Collection<Collection<string>>
gebunden ist.
Ich habe keine Spalten in Code-behind definiert vor, so ist hier ein Beispiel in XAML. Ich habe festgestellt ComboBoxColumn kann manchmal schwierig sein, so dass ich gezeigt habe, wie Sie eine Combobox in der Spalte entweder durch Verwendung einer Template oder eine ComboBoxColumn haben können. Ich habe Kopie von meinem eigenen Code eingefügt, so ersetzen Sie einfach ‚dg‘ mit ‚WPFToolkit‘ in Ihrem Fall:
<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>
Ich gehe davon aus, dass die Operation wird das ausgewählte Element, sind Daten die Elemente zur Auswahl, und dass Ihr Datagrid ist eine Sammlung von StatsOperation gebunden. Viel Glück!
Um die Itemssource Binding Fehler verwenden Sie das Formular zu beheben:
BindingOperations.SetBinding(new DataGridComboBoxColumn(), DataGridComboBoxColumn.ItemsSourceProperty, new Binding("Data"));
Sie können natürlich nicht tun dies in dem intializer, so dass Sie Ihre Erklärungen um ein Stückchen bewegen müssen werden, aber das sollte diesen Fehler in der Update kümmern.
Bearbeiten Es tut mir leid, ich bin etwas langsam midnights :). Hier ist eine aktualisierte Antwort. Es sieht aus wie großer Artikel von Vincent Sibal
Partial - Ich denke, es ist eine Verwirrung in dem, was Sie sagen. Sie sagten, Sie eine Sammlung von Sammlung von Zeichenketten in jeder Reihe müssen, so dass die Combo-Box verschiedenen Saiten für verschiedene Zeilen zeigen konnte. Doch für ein Kombinationsfeld eine Reihe von Strings zu zeigen, müssen Sie nur eine Sammlung von Strings, pro Zeile, nicht eine Sammlung von Sammlung von Strings. Nun, da Sie die Sammlung von Strings pro Zeile müssen Sie denken vielleicht, dass Sie Sammlung Sammlung von Strings benötigen würde. Ist mein Verständnis für Ihre Frage richtig? Wenn ja, dann Erwähnung Sammlung Sammlung von Strings ist falsch. Was Sie wirklich brauchen ist eine Sammlung von StatOperations, in dem jeder StatOperation eine Sammlung von Zeichenketten haben sollte. Das ist genau, wie Sie wie in Ihren Klassen oben gezeigt hatte. Um Fortschritte zu machen, empfehle ich Ihnen Ihre Frage bearbeiten und zeigen, wo genau waren Sie stecken nach der Bindung wie von AndyG fixieren.