问题
How can I bind the ItemsSource of a Combobox column to a collection that is a sub-property of a property on the same row? In other words, the DataGrid is bound to a collection of items of a class the contains Property1 and Property2. So the DataGrid has two columns, Property1 and Property2. Property1 has a sub-property that is an Observable Collection. The column for Property2 is a Combobox column that should use Property1's Observable Collection as its ItemsSource.
I'm loading the grid's source data via EFCore. I have made sure to use ".Include" to be sure Property1's Observable Collection is getting loaded into memory. I'm wondering if the issue is that the UI is not made aware that Property1's Observable Collection has been updated when it is loaded from the database? If that's the issue, how could I correct this?
I need this collection to serve as the ItemsSource for the Property2 column shown below. I've tried using relative source to get the datacontext of the grid, but it is not working.
<wct:DataGridComboBoxColumn Binding="{Binding Property2, Mode=TwoWay}"
ItemsSource="{Binding Path=DataContext.Property1.MyCollection,
RelativeSource={RelativeSource TemplatedParent},
Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
I've also tried this:
ItemsSource="{Binding ElementName=grid,
Path=DataContext.Property1.MyCollection}"
Thanks.
回答1:
Derive official processing method, the better way is set DataGridComboBoxColumn
in the code behind. Give DataGridComboBoxColumn
a tag name and find the column with tag like the following then set DataGridComboBoxColumn
ItemsSource
.
MyCollection = new List<string> { "DD", "FF", "CC" };
var comboBoxColumn = MyDataGrid.Columns.FirstOrDefault(x => x.Tag.Equals("Link")) as DataGridComboBoxColumn;
if (comboBoxColumn != null)
{
comboBoxColumn.ItemsSource = MyCollection;
}
MyDataGrid.ItemsSource = items;
Xaml Code
<controls:DataGridComboBoxColumn
Width="*"
Binding="{Binding p2}"
Header="Link"
Tag="Link"
/>
DataGridComboBoxColumn
ItemsSource property could not access data source sub property directly, so we need make a list property for the Page class that uses to store Property1.MyCollection
. If you already make MyCollection propety for the Page class, you could also use x:bind to access like the following.
<controls:DataGridComboBoxColumn
Width="*"
Binding="{Binding p2}"
Header="Link"
ItemsSource="{x:Bind MyCollection,Mode=OneWay}"
Tag="Link"
/>
Update
If the Property1.MyCollection is not constant list, you could try to use DataGridTemplateColumn
custom column cell and bind the data source like the following
<controls:DataGridTemplateColumn>
<controls:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
ItemsSource="{Binding p1.Mycollection, Mode=OneWay}"
SelectionChanged="ComboBox_SelectionChanged"
/>
</DataTemplate>
</controls:DataGridTemplateColumn.CellEditingTemplate>
<controls:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock
Margin="10"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Text="{Binding p2, Mode=OneWay}"
/>
</DataTemplate>
</controls:DataGridTemplateColumn.CellTemplate>
</controls:DataGridTemplateColumn>
Code behind
public class P1
{
public string Name { get; set; }
public List<string> Mycollection { get; set; }
}
public class ITPP
{
public P1 p1 { get; set; }
public string p2 { get; set; }
}
private void CreateDataSource()
{
items = new List<ITPP>();
items.Add(new ITPP { p1 = new P1 { Name = "FirstP1", Mycollection = new List<string>() { "AA", "BB", "CC", "DD" } }, p2 = "CC" });
items.Add(new ITPP { p1 = new P1 { Name = "SecondP1", Mycollection = new List<string>() { "EE", "FF", "GG", "HH" } }, p2 = "HH" });
items.Add(new ITPP { p1 = new P1 { Name = "ThirdP1", Mycollection = new List<string>() { "II", "JJ", "KK", "LL" } }, p2 = "LL" });
MyDataGrid.ItemsSource = items;
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var mycombobox = sender as ComboBox;
var p1collection = mycombobox.ItemsSource;
foreach (var item in items)
{
if (item.p1.Mycollection == p1collection)
{
item.p2 = mycombobox.SelectedItem as string;
}
}
}
来源:https://stackoverflow.com/questions/60837543/how-can-i-use-a-collection-on-the-data-item-row-of-my-windows-community-template