如何为 DataGridTemplate 中的每个组合框 change/prepopulate SelectedIndex?
How to change/prepopulate SelectedIndex for each individual Combobox in DataGridTemplate?
我目前有一个包含 2 列的 DataGrid,其中一列是 DataGridTextColumn,它将显示字符串 ObservableCollection 中的项目,第二列是 DataGridTemplateColumn,其中包含 DataGridCellTemplate,其中包含显示 Combobox 的 DataTemplate .组合框还绑定到字符串的 ObservableCollection。一切都按应有的方式绑定和显示。
我想要实现的是,由于需求的变化和功能的增加,我需要更改显示在组合框(当前索引为 0)。我有一个新字典,其中包含第一列中的条目作为键,值是存在于第二列(组合框)中的字符串。
即: 如何将第二列中某些组合框的 selectedIndex 更改为 'pre-select' 从字典中获取的已知条目的索引?
一个最小的、完整的、可验证的例子:
我目前拥有的:
+--------------+-------------------+
| CustomerName | Location |
+--------------+-------------------+
| Bob | <Select Location> | <-- these are comboboxes
| John | <Select Location> |
| Katy | <Select Location> |
+--------------+-------------------+
XAML:
<DataGrid x:Name="CustomerLocationGrid" Height="265" VerticalAlignment="Center" Margin="-7,8,-2,-6" ItemsSource="{Binding CustomerNameList}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn x:Name="customerDisplayList" Header="CustomerName" MinWidth="500" IsReadOnly="True" Binding="{Binding Path=., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DisplayIndex="0"/>
<DataGridTemplateColumn x:Name="networkTypeTemplateColumn" Header="Location" MinWidth ="200" CanUserResize="True" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox x:Name="locationCombobox" ItemsSource="{Binding locationList, RelativeSource={RelativeSource AncestorType=UserControl}}" SelectedIndex="0" SelectionChanged="locationCombobox_SelectionChanged"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
其中:
public ObservableCollection<String> CustomerNameList { get; set; } //has a collection of Bob, John, Katy
public ObservableCollection<string> locationList { get; set;} //has locations like Minnesota, Iowa, New York
(列表来自不同的来源)
注意上面的 DataTemplate-Combobox XAML 是我从 this tutorial on WPF comboboxes(名为 "The Best WPF Combobox Tutorial Ever")
那里学到的
以及我如何从另一个来源获得第三个 Dictionary<string,string>
,它具有 Bob -> Minnesota
、John -> Iowa
的映射,但 Katy 不在那里,因为它无法预先确定并且用户需要手动 select 位置。
我想自动 select 组合框内的索引 以便 table 看起来像这样,或者更改 Bob 和 Johns 的位置:
+--------------+-------------------+
| CustomerName | Location |
+--------------+-------------------+
| Bob | Minnesota | <-- set as the displayedIndex
| John | Iowa |
| Katy | <Select Location> |
+--------------+-------------------+
我试过的:
我的方法是遍历每个 CustomerName 条目,在字典中查找它,如果从字典返回一个值,则设置位置。字符串都是相同的,因此不需要匹配。
以编程方式循环遍历 DataGridTemplateColumn 以获取每个组合框并设置 selectedIndex,但无法获取每个客户组合框的索引以及客户名
尝试利用 Initialized
事件处理程序(这样做的灵感来自 this answer)来使用对象(用 sender as ComboBox
铸造,但不能获取索引。
我也尝试过使用相关的解决方案,如 ,但觉得它太复杂了(也无法获得父级)和其他一些基于 VisualTreeHelper 方法的解决方案。
如果您使用 Name
和 Location
属性 创建一个 Customer
ViewModel class 并创建一个 ObservableCollection<Customer> customers
会很容易并将其设置为数据网格的 ItemsSource
并使用它来绑定列。
public class Customer
{
public string Name {get; set;}
public string Location {get; set;}
}
ObservableCollection<Customer> customers = new ObservableCollection<Customer>();
使用 CustomerNamesList
和适当的 locationList
中的名称填充 customers
集合
foreach(var customer in CustomerNameList )
{
string location = string.Empty;
//ThirdList is your Dictionary<string, string>
if(ThirdList.Contains(customerName)) // Get customer location
location = ThirdList[customerName];
customers.Add(new Customer{Name=cusotmerName, Location=location});
}
在 XAML 中创建一个名为 CustomerViewSource
的 CollectionViewSource
并将其绑定到数据网格的 ItemsSource
<UserControl.Resources>
<CollectionViewSource x:Key="CustomerViewSource"/>
</UserControl.Resources>
在后面的代码中,将 CustomerViewSource.Source
设置为 ObservableCollection<Customer> customers
CollectionViewSource CustomerViewSource = this.Resources["CustomerViewSource"] as CollectionViewSource;
CustomerViewSource.Source = customer;
在XAML中,将DataGridTextColumn
的绑定设置为customers
集合的Name
属性并设置ComboBox.SelectedItem
' s 绑定到 Location
<DataGrid x:Name="CustomerLocationGrid" Height="265" VerticalAlignment="Center" Margin="-7,8,-2,-6" AutoGenerateColumns="False"
ItemsSource="{Binding Source={StaticResource CustomerViewSource}, UpdateSourceTrigger=PropertyChanged}" >
<DataGrid.Columns>
<DataGridTextColumn x:Name="customerDisplayList" Header="CustomerName" MinWidth="500" IsReadOnly="True" Binding="{Binding Name}"/>
<DataGridTemplateColumn x:Name="networkTypeTemplateColumn" Header="Location" MinWidth ="200" CanUserResize="True" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox x:Name="locationCombobox" ItemsSource="{Binding locationList, RelativeSource={RelativeSource AncestorType=UserControl}}"
SelectedItem="{Binding Location}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
现在,您的数据网格将显示所有预填充的客户信息,对于没有位置信息的客户,用户将能够select它,您可以在 customers
集合中检索它
我目前有一个包含 2 列的 DataGrid,其中一列是 DataGridTextColumn,它将显示字符串 ObservableCollection 中的项目,第二列是 DataGridTemplateColumn,其中包含 DataGridCellTemplate,其中包含显示 Combobox 的 DataTemplate .组合框还绑定到字符串的 ObservableCollection。一切都按应有的方式绑定和显示。
我想要实现的是,由于需求的变化和功能的增加,我需要更改显示在组合框(当前索引为 0)。我有一个新字典,其中包含第一列中的条目作为键,值是存在于第二列(组合框)中的字符串。
即: 如何将第二列中某些组合框的 selectedIndex 更改为 'pre-select' 从字典中获取的已知条目的索引?
一个最小的、完整的、可验证的例子:
我目前拥有的:
+--------------+-------------------+
| CustomerName | Location |
+--------------+-------------------+
| Bob | <Select Location> | <-- these are comboboxes
| John | <Select Location> |
| Katy | <Select Location> |
+--------------+-------------------+
XAML:
<DataGrid x:Name="CustomerLocationGrid" Height="265" VerticalAlignment="Center" Margin="-7,8,-2,-6" ItemsSource="{Binding CustomerNameList}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn x:Name="customerDisplayList" Header="CustomerName" MinWidth="500" IsReadOnly="True" Binding="{Binding Path=., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DisplayIndex="0"/>
<DataGridTemplateColumn x:Name="networkTypeTemplateColumn" Header="Location" MinWidth ="200" CanUserResize="True" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox x:Name="locationCombobox" ItemsSource="{Binding locationList, RelativeSource={RelativeSource AncestorType=UserControl}}" SelectedIndex="0" SelectionChanged="locationCombobox_SelectionChanged"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
其中:
public ObservableCollection<String> CustomerNameList { get; set; } //has a collection of Bob, John, Katy
public ObservableCollection<string> locationList { get; set;} //has locations like Minnesota, Iowa, New York
(列表来自不同的来源)
注意上面的 DataTemplate-Combobox XAML 是我从 this tutorial on WPF comboboxes(名为 "The Best WPF Combobox Tutorial Ever")
那里学到的以及我如何从另一个来源获得第三个 Dictionary<string,string>
,它具有 Bob -> Minnesota
、John -> Iowa
的映射,但 Katy 不在那里,因为它无法预先确定并且用户需要手动 select 位置。
我想自动 select 组合框内的索引 以便 table 看起来像这样,或者更改 Bob 和 Johns 的位置:
+--------------+-------------------+
| CustomerName | Location |
+--------------+-------------------+
| Bob | Minnesota | <-- set as the displayedIndex
| John | Iowa |
| Katy | <Select Location> |
+--------------+-------------------+
我试过的: 我的方法是遍历每个 CustomerName 条目,在字典中查找它,如果从字典返回一个值,则设置位置。字符串都是相同的,因此不需要匹配。
以编程方式循环遍历 DataGridTemplateColumn 以获取每个组合框并设置 selectedIndex,但无法获取每个客户组合框的索引以及客户名
尝试利用
Initialized
事件处理程序(这样做的灵感来自 this answer)来使用对象(用sender as ComboBox
铸造,但不能获取索引。
我也尝试过使用相关的解决方案,如
如果您使用 Name
和 Location
属性 创建一个 Customer
ViewModel class 并创建一个 ObservableCollection<Customer> customers
会很容易并将其设置为数据网格的 ItemsSource
并使用它来绑定列。
public class Customer
{
public string Name {get; set;}
public string Location {get; set;}
}
ObservableCollection<Customer> customers = new ObservableCollection<Customer>();
使用 CustomerNamesList
和适当的 locationList
customers
集合
foreach(var customer in CustomerNameList )
{
string location = string.Empty;
//ThirdList is your Dictionary<string, string>
if(ThirdList.Contains(customerName)) // Get customer location
location = ThirdList[customerName];
customers.Add(new Customer{Name=cusotmerName, Location=location});
}
在 XAML 中创建一个名为 CustomerViewSource
的 CollectionViewSource
并将其绑定到数据网格的 ItemsSource
<UserControl.Resources>
<CollectionViewSource x:Key="CustomerViewSource"/>
</UserControl.Resources>
在后面的代码中,将 CustomerViewSource.Source
设置为 ObservableCollection<Customer> customers
CollectionViewSource CustomerViewSource = this.Resources["CustomerViewSource"] as CollectionViewSource;
CustomerViewSource.Source = customer;
在XAML中,将DataGridTextColumn
的绑定设置为customers
集合的Name
属性并设置ComboBox.SelectedItem
' s 绑定到 Location
<DataGrid x:Name="CustomerLocationGrid" Height="265" VerticalAlignment="Center" Margin="-7,8,-2,-6" AutoGenerateColumns="False"
ItemsSource="{Binding Source={StaticResource CustomerViewSource}, UpdateSourceTrigger=PropertyChanged}" >
<DataGrid.Columns>
<DataGridTextColumn x:Name="customerDisplayList" Header="CustomerName" MinWidth="500" IsReadOnly="True" Binding="{Binding Name}"/>
<DataGridTemplateColumn x:Name="networkTypeTemplateColumn" Header="Location" MinWidth ="200" CanUserResize="True" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox x:Name="locationCombobox" ItemsSource="{Binding locationList, RelativeSource={RelativeSource AncestorType=UserControl}}"
SelectedItem="{Binding Location}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
现在,您的数据网格将显示所有预填充的客户信息,对于没有位置信息的客户,用户将能够select它,您可以在 customers
集合中检索它