【问题标题】:How to change/prepopulate SelectedIndex for each individual Combobox in DataGridTemplate?如何为 DataGridTemplate 中的每个单独的 Combobox 更改/预填充 SelectedIndex?
【发布时间】:2015-07-15 16:52:14
【问题描述】:

我目前有一个包含 2 列的 DataGrid,其中一列是 DataGridTextColumn,它将在字符串的 ObservableCollection 中显示项目,第二列是 DataGridTemplateColumn,它包含 DataGridCellTemplate,其中包含显示 Combobox 的 DataTemplate。组合框还绑定到字符串的 ObservableCollection。一切都按应有的方式绑定和显示。

我想要实现的是,由于需求的变化和功能的增加,我需要更改 Combobox 中显示的默认条目的索引(当前索引为 0 )。我有一个新字典,其中包含第一列中的条目作为键,值是第二列(组合框)中存在的字符串。

即:如何更改第二列中某些组合框的 selectedIndex 以“预选”从字典中获取的已知条目的索引?

一个最小的、完整的、可验证的例子:

我目前拥有的:

+--------------+-------------------+
| 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 学到的(命名为“有史以来最好的 WPF Combobox 教程”)

以及我如何拥有第三个Dictionary&lt;string,string&gt;,它来自另一个具有Bob -&gt; MinnesotaJohn -&gt; Iowa 映射的来源,但 Katy 不存在,因为它无法预先确定,用户需要手动选择位置。

我想自动选择组合框内的索引,使表格看起来像这样,或者更改 Bob 和 Johns 的位置:

+--------------+-------------------+
| CustomerName |     Location      |
+--------------+-------------------+
| Bob          | Minnesota         | <-- set as the displayedIndex
| John         | Iowa              |
| Katy         | <Select Location> |
+--------------+-------------------+

我的尝试: 我的方法是遍历每个 CustomerName 条目,在字典中查找,如果从字典返回值,则设置位置。字符串都是相同的,因此不需要匹配。

  • 以编程方式循环遍历 DataGridTemplateColumn 以获取每个组合框并设置 selectedIndex,但未能获取每个客户组合框的索引以及客户名称

  • 尝试利用Initialized 事件处理程序(这样做的灵感来自this answer)来使用对象(使用sender as ComboBox 进行转换,但无法获取索引。

    李>

我也尝试过使用相关解决方案,例如 getting the index with VisualTreeHelper,但觉得太复杂(也无法获取父级)以及其他一些基于 VisualTreeHelper 方法的解决方案。

【问题讨论】:

    标签: c# wpf xaml datagrid combobox


    【解决方案1】:

    如果您创建一个带有NameLocation 属性的Customer ViewModel 类并创建一个ObservableCollection&lt;Customer&gt; 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 中创建一个名为 CustomerViewSourceCollectionViewSource 并将其绑定到数据网格的 ItemsSource

    <UserControl.Resources>
        <CollectionViewSource x:Key="CustomerViewSource"/>
    </UserControl.Resources>
    

    在后面的代码中,将CustomerViewSource.Source 设置为ObservableCollection&lt;Customer&gt; customers

    CollectionViewSource CustomerViewSource = this.Resources["CustomerViewSource"] as CollectionViewSource;
    CustomerViewSource.Source = customer;
    

    在 XAML 中,将customers 集合的DataGridTextColumn 的绑定设置为Name 属性,并将ComboBox.SelectedItem 的绑定设置为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>
    

    现在,您的数据网格将显示所有预填充的客户信息,对于那些没有位置信息的用户将能够选择它,您可以在 customers 集合中检索它

    【讨论】:

    • 感谢您的回答,我已经调整了更改,现在它使用所描述的 ViewModel,但是即使 Customer 类的 Location 属性中存在 vlue,我的 Comboboxes 也会显示空白
    • 我已经解决了这个问题,原来从ThirdList 保存在Location 中的字符串之一与要在绑定到@987654348 的组合框中显示的字符串不匹配@。例如 NewYorkNew York。非常感谢,您是专家!
    • 还要添加此答案以供将来参考,可能需要在SelectedItem 中添加UpdateSourceTrigger=PropertyChanged 绑定Combobox,如下所示:SelectedItem="{Binding Location, UpdateSourceTrigger=PropertyChanged}",以确保属性得到相应更新。
    猜你喜欢
    • 1970-01-01
    • 2013-05-20
    • 1970-01-01
    • 2016-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多