我在XAML中创建了一个DataGrid,并且ItemsSource被绑定到包含属性的某个类的ObservableCollection。然后在C#中,我创建了一个DataGridTextColumn和一个DataGridComboBoxColumn,并将这些绑定到ObservableCollection内对象的属性。我可以将DataGridComboBoxColumn绑定到一个简单的Collection,但我想要做的是将它绑定到一组字符串集合,这样对于每一行,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_
};
//...
非常感谢任何帮助!
好的,所以在看了两个第一个答案之后我发现了一些东西。我的绑定真的不对!现在,我想要做的是类似于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如何绑定到数据?
答案 0 :(得分:11)
首先,这应该很容易......其次,为什么要在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;
}
结果:
答案 1 :(得分:4)
我认为错误在于你是如何完成绑定的。定义列时,绑定与特定行表示的对象相关。据我所知,每行都有一个StatsOperation,因此TextBox列绑定到操作,这就是你的方式,ComboBox列ItemsSource应绑定到Collection。现在它看起来像是Collection<Collection<string>>
。
我之前没有在代码隐藏中定义列,所以这里是XAML中的一个例子。我发现ComboBoxColumn有时会很棘手,所以我已经展示了如何使用TemplateColumn或ComboBoxColumn在列中添加组合框。我从我自己的代码中复制粘贴,所以在你的情况下用'WPFToolkit'替换'dg':
<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 :(得分:2)
要修复ItemsSource绑定错误,请使用以下格式:
BindingOperations.SetBinding(new DataGridComboBoxColumn(), DataGridComboBoxColumn.ItemsSourceProperty, new Binding("Data"));
您显然无法在初始化程序中执行此操作,因此您必须稍微移动声明,但这应该会在更新中处理该错误。
答案 3 :(得分:1)
编辑对不起,我在中午的时候有点慢:)。这是一个更新的答案。看起来文森特·西巴尔WPF DataGrid - DataGridComboBoxColumn v1 Intro的精彩文章回答了你的问题。是吗?
答案 4 :(得分:0)
部分 - 我认为您所说的内容存在混淆。您说您需要在每一行中收集字符串集合,以便组合框可以显示不同行的不同字符串。但是,对于显示一组字符串的组合框,您只需要每行一个字符串集合,而不是字符串集合的集合。
既然你需要每行收集字符串,你可能会认为你需要收集字符串集合。
我对你的问题的理解是否正确?如果是这样,那么你提到的字符串集合是错误的。
您实际需要的是StatOperations的集合,其中每个StatOperation都应该包含一组字符串。这正是您在上面的课程中所显示的内容。
为了取得进展,我建议你编辑你的问题,并指出在修复AndyG建议的绑定后你到底陷入了什么位置。
答案 5 :(得分:0)
让我们将 ComboBox 的 ItemsSource 绑定到一个属性,例如您的视图模型的当前选择。此属性应根据您当前的数据网格行选择返回一个过滤列表。 CompareWithSelectedRow 只是一个用于说明示例的伪函数。每次,当您单击 ComboBox 以填充选择列表时,此属性将被调用并返回正确的选择列表。参见下面的例子,EntireChoiceList 是一个由字符串和列表组成的元组列表。有改进的空间,例如使用字典或查找。
List<(string Key, List<string> Choices)> EntireChoiceList= new List<(string, List<string>)>();
public List<string> CurrentChoices
{
get => CurrentChoices.Where(q => CompareWithSelectedRow(q.Key, CurrentRow )).FirstOrDefault().Choices;
}
public object CurrentRow { get => ItemsView.CurrentItem; }
bool CompareWithSelectedRow(string key, object row)
{
return key == row; // here you should define compare expression
}
使用 CollectionViewSource 获取数据网格中的选定行。 Items 是绑定到数据网格的视图模型中的列表。
ItemsView = (CollectionView)CollectionViewSource.GetDefaultView(Items);
ItemsView.CurrentItem