【问题标题】:How to get selection from ComboboxColumn in specific row?如何从特定行中的 ComboboxColumn 中获取选择?
【发布时间】:2014-01-03 11:47:38
【问题描述】:

我不知道如何在选择后正确地从 ComboboxColumn 单元格返回值。我的 ComboboxColum 如下所示:

<DataGridComboBoxColumn CanUserSort="False" 
                        x:Name="cbcList" 
                        DisplayMemberPath="{Binding Person, Converter={StaticResource converter}}" 
                        Header="Person"/>

ItemsSource 在后面的代码中设置为Person 对象列表。现在,我如何获取从该列中的所有选择中生成的 Person 对象列表?我尝试创建Person obejcts 的新列表并使用SelectedItemBinding 绑定它,但这样做要么是错误的方式,要么是我犯了一些错误。

【问题讨论】:

    标签: c# wpf datagridcomboboxcolumn


    【解决方案1】:

    SelectedItem 没有属性设置器,这意味着您无法为其分配绑定。但是,我们可以通过 SelectionChanged 事件跟踪多个选择。

    假设:您在 ViewModel 中有一个名为 People 的 ObservableCollection。

    在 ViewModel 中创建一个名为 SelectedPeople 的 Collection 属性

    Public Collection<Person> SelectedPeople { get; set; }
    

    在 XAML 中实现 SelectionChanged 事件。

    <DataGrid ItemsSource="{Binding Path=People}" SelectionChanged="Selector_OnSelectionChanged" />
    

    后面代码中的 SelectionChanged 处理程序将如下所示。

    private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (e.AddedItems != null)
        {
            e.AddedItems.OfType<Person>()
                .ToList()
                .ForEach(ViewModel.SelectedPeople.Add);
        }
    
        if (e.RemovedItems != null)
        {
            e.RemovedItems.OfType<Person>()
                .ToList()
                .ForEach(p => ViewModel.SelectedPeople.Remove(p));
        }
    }
    

    为简洁起见,我删除了异常管理。

    编辑 - 以上是关于处理来自 DataGrid 的多个选择。我已将上面的 PersonModel 重命名为 Person。它是将数据暴露给视图的模型。 ViewModel 是管理模型和用于操作模型的功能的类。如需更多信息,请谷歌MVVM pattern

    关于您最初的问题,处理 DataGridComboBoxColumn 和 DataGrid 之间的绑定,我创建了一个示例。下面的代码可以复制到新项目中。

    Person 模型是

    public class Person
    {
        public string FirstName { get; set; } 
        public string Surname { get; set; }
        public string MiddleName { get; set; }
        public int Age { get; set; }
    }
    

    ViewModel 是

    public class MyViewModel
    {
        public MyViewModel()
        {
            this.People = new ObservableCollection<Person>()
            {
                new Person() { FirstName = "A", Surname = "B", MiddleName = "C", Age = 1},
                new Person() { FirstName = "D", Surname = "E", MiddleName = "F", Age = 2},
                new Person() { FirstName = "G", Surname = "H", MiddleName = "I", Age = 3},
                new Person() { FirstName = "J", Surname = "K", MiddleName = "L", Age = 4},
                new Person() { FirstName = "M", Surname = "N", MiddleName = "O", Age = 5}
            };
    
            this.Items = new ObservableCollection<GridItem>()
            {
                new GridItem() { Person = this.People[0]},
                new GridItem() { Person = this.People[1]},
                new GridItem() { Person = this.People[2]},
                new GridItem() { Person = this.People[3]}
            };
        }
    
        public ObservableCollection<Person> People { get; set; }
    
        public ObservableCollection<GridItem> Items { get; set; }
    
    }
    

    View 背后的代码只是创建和公开 ViewModel。

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            ViewModel = new MyViewModel();
            InitializeComponent();
        }
    
        public MyViewModel ViewModel { get; set; }
    }
    

    将所有乐趣留在 Xaml 中。

    <Window x:Class="StackOverflow._20902950.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:this="clr-namespace:StackOverflow._20902950"
            DataContext="{Binding RelativeSource={RelativeSource Self}, Path=ViewModel}"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <DataGrid ItemsSource="{Binding Path=Items}" AutoGenerateColumns="False">
                <DataGrid.Columns>
                    <DataGridComboBoxColumn Header="Person" Width="100" DisplayMemberPath="FirstName" SelectedItemBinding="{Binding Path=Person}">
                        <DataGridComboBoxColumn.ElementStyle>
                            <Style TargetType="{x:Type ComboBox}">
                                <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type this:MainWindow}}, Path=ViewModel.People}" />
                            </Style>
                        </DataGridComboBoxColumn.ElementStyle>
                        <DataGridComboBoxColumn.EditingElementStyle>
                            <Style TargetType="{x:Type ComboBox}">
                                <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type this:MainWindow}}, Path=ViewModel.People}" />
                            </Style>
                        </DataGridComboBoxColumn.EditingElementStyle>
                    </DataGridComboBoxColumn>
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
    </Window>
    

    此命名空间将需要更改为您项目的命名空间。

    我希望这会有所帮助。

    【讨论】:

    • 我是新手,尝试您的代码时遇到了一些问题。我按照说明创建了集合,就是这样。我不知道我需要添加哪些命名空间,因为 ViewModel 未被识别。我不知道您的代码中的 &lt;PersonModel&gt; 是什么。我对SelectionChanged 事件也有一些疑问。我有 2 个 ItemsSoures(1 个用于 DataGrid,1 个用于 ComboboxColumn)。以你已经完成的方式编写它应该触发它任何选择被更改,对吧?因此,如果我理解正确的话,不仅是 Combobox。
    • 我明白了。我给了你错误的答案。我会尽快更新我的答案。
    • 我在这里找到了另一个解决我的问题的方法:stackoverflow.com/questions/19003133/… 我一定已经对我的代码进行了相当多的更改,但它确实有效。我想过这样的解决方案,但到目前为止我还找不到合适的工具。不过谢谢你的回答,干杯!
    • 我已经更新了您问题的答案。很高兴你解决了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多