【问题标题】:DataGridComboBoxColumn Values from Custom Class自定义类中的 DataGridComboBoxColumn 值
【发布时间】:2011-12-21 13:19:45
【问题描述】:

我有一个 CommentsData 类,它用于在 DataGrid 中加载、操作和保存值。我想让类中的状态字段显示为网格中的下拉列表。注释值只需填充一次。我尝试了很多变化,但这不起作用。组合是空白的。 I need to be able to populate the values in the combo and when the selection changes the value should remain there and not dissappear.

这是网格的 Xaml(更新 2)

<DataGrid Grid.Row="2" AutoGenerateColumns="False"  Height="Auto" HorizontalAlignment="Stretch" Name="grdComments" VerticalAlignment="Stretch" CanUserAddRows="True" CanUserDeleteRows="True" BeginningEdit="grdComments_BeginningEdit" InitializingNewItem="grdComments_InitializingNewItem" PreviewKeyDown="grdComments_PreviewKeyDown" SizeChanged="grdComments_SizeChanged">
  <DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding Path=Author}" Header="Author" />
    <DataGridTemplateColumn Header="Status" >
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <ComboBox  ItemsSource="{Binding UserValues}" DisplayMemberPath="UserStatus" SelectedValuePath="UserStatus" SelectedValue="{Binding Status, UpdateSourceTrigger=PropertyChanged}" />
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
    <DataGridTextColumn Binding="{Binding Path=Comment}" Header="Comment" Width="570" />
  </DataGrid.Columns>

这是 CommentData 类的代码(更新 2)

public class CommentsData 
{

    public string Author { get; set; }
    public string Status { get; set; }
    public string Comment { get; set; }
    public string Username { get; set; }

    public ObservableCollection<StatusValue> UserValues { get; set; }

    public CommentsData()
    {
        UserValues = new ObservableCollection<StatusValue>();

        UserValues.Add(new StatusValue("New"));
        UserValues.Add(new StatusValue("Open"));
        UserValues.Add(new StatusValue("ReOpen"));
        UserValues.Add(new StatusValue("Closed"));

    }

}

public class StatusValue
{
    public string UserStatus { get; set; }

    public StatusValue (string value)
    {
        UserStatus = value;
    }
}

这里是初始化cmets列表的代码

private List<CommentsData> _commentsList;

private void InitializeObjects()
{
        _commentsList = new List<CommentsData>();
        grdComments.ItemsSource = _commentsList;

}

感谢所有反馈,以上代码正常运行

【问题讨论】:

    标签: c# wpf data-binding datagridcomboboxcolumn


    【解决方案1】:

    正如 MSDN 文章中关于 DataGridComboBoxColumn 填充下拉列表中所述,您必须首先使用以下选项之一设置 ComboBox 的 ItemsSource 属性:

    • 静态资源。
    • 一个 x:静态代码实体。
    • ComboBoxItem 类型的内联集合。

    如果您想将ComboBox.ItemsSource 绑定到对象属性,使用DataGridTemplateColumn 更容易,如下所示:

    <DataGridTemplateColumn Header="Status">
         <DataGridTemplateColumn.CellTemplate>
             <DataTemplate>
                  <ComboBox ItemsSource="{Binding UserValues}" DisplayMemberPath="UserStatus" SelectedValuePath="UserStatus" SelectedValue="{Binding Status, UpdateSourceTrigger=PropertyChanged}" />
             </DataTemplate>
         </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
    

    【讨论】:

    • 列表正在填充,选择也仍然存在,但是当我尝试从 DataGrid 获取数据以保存它时,状态值始终保持新并且不反映更改的值跨度>
    • @CodeMe,我忘记在 SelectedValue 绑定中添加 UpdateSourceTrigger。我正在更新代码,现在应该可以工作了。
    • UpdateSourceTrigger 是否需要 INotifyPropertyChanged 实现?
    • @CodeMe, INotifyPropertyChanged 如果您想从代码中更改属性,则需要实现,以便您的 GUI 可以检测并显示更改。如果你只是想从ComboBox中选择值,就这样,你可以不用这个接口。
    • @CodeMe,那么您应该指定如何设置DataGrid.ItemsSource。这种方法只有在具有 UserValues 的类是 DataGrid 的 DataContext 时才有效。
    【解决方案2】:

    我发现您的代码中缺少一些内容

    首先,你的类没有实现INotifyPropertyChanged。这意味着,如果 CommentData 上的属性发生更改,它不会告诉 UI 已更改,因此 UI 不会更新以显示新值。

    其次,您告诉您的ComboBox,每个项目上都有一个名为Status 的属性,并将其用作ComboBoxItem.Value,但是StatusValue 上不存在此属性。将其更改为引用UserStatus,这是StatusValue 上的有效属性。

    SelectedValuePath="UserStatus"
    

    最后,你真的不应该在每个项目上重新创建 ComboBox 项目。相反,在 ViewModel 层次结构中的某个位置创建集合,或使其成为静态资源。

    例如,如果包含您的CommentsData 集合的类也包含您的StatusValues 集合,您可以使用RelativeSource 绑定来绑定它,如下所示:

    ItemsSource="{Binding 
        RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},
        Path=DataContext.UserValues}"
    

    【讨论】:

    • 根据@Rachel 的建议,INotifyPropertyChanged 已实施,SelectedValuePath 也已更新,并且该集合已移至维护 cmets 列表的位置。现在组合列表是空的,我已经更新了代码,所以你可以看看。
    • @CodeMe 我没有看到你的DataGrid.ItemsSource 绑定到CommentListDataGridDataContext 是什么?它应该是包含CommentListUserValues 列表的任何类,但是如果是这种情况,我会在DataGrid 上看到ItemsSource="{Binding CommentList}"
    • 抱歉忘记提了,我已经更新了这个grdComments.ItemsSource = _commentsList;的代码。包含这两个集合的类是我的窗口类
    • @CodeMe 您的DataGrid 的DataContext 是否等于包含您的CommentListUserValues 的类?否则,RelativeSource 绑定将不起作用。您可以通过将 DataGrid 的 ItemsSource 属性绑定到 XAML 中的 CommentList 来判断 DataContext 是否正确(ItemsSource="{Binding _commentsList}"。如果 DataContext 不是该类,您始终可以在后面的代码中使用 grdComments.DataContext = this; 来设置它
    • DataContext 对我不起作用,但由于原始问题已解决,我将重新发布它以将集合移动到窗口类
    【解决方案3】:

    这是我将使用的 DataGridComboboxColumn:

    <DataGridTemplateColumn>
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <ComboBox ItemsSource="{Binding UserValues}" SelectedItem="{Binding Status}" DisplayMemberPath="UserStatus" />
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
    

    另外CommentsData.Status应该是StatusValue类型,而不是string,这样你就可以绑定SelectedItem就可以了。

    【讨论】:

    • CommentsData.Status 成为一个字符串非常好。我通常建议人们使用SelectedValue而不是SelectedItem来绑定所选项目,因为SelectedItem是通过引用,这意味着如果它没有指向与ItemsSource中的版本完全相同的内存引用,它不会被选中。
    • 我推荐使用CommentsData.Status 类型的StatusValue 正是因为SelectedItem。我个人建议使用SelectedItem,因此所选项目 绑定到项目源的列表项目之一,尤其是在使用 MVVM 模式时(您希望 Selected Item 实例具有相同的作为数据源中的项目引用)。
    • 我想每个人都有自己的喜好。我通常进行一次数据库调用以获取 ComboBox 值的列表,然后进行第二次数据库调用以获取记录。如果绑定SelectedItem,我必须确保获取记录的第二个数据库调用附加了从第一个数据库调用获得的 ComboBox 项,并且不会从数据库创建或加载它自己的副本。这尤其是 ORM 系统(例如 Entity Framework)的一个问题,它会自动创建相关项目。
    • 当我将CommentsData.Status 设置为StatusValue 类型时,它没有显示选定的项目,这可能是因为您已经讨论过上述问题,但我现在应该怎么做?
    • 如果CommentsData.Status 的类型是StatusValue,那么您必须使用SelectedItem 进行绑定,而不是SelectedValue。请参阅上面的代码以获取正确的绑定。我已经测试了上面的代码,它对我有用。
    猜你喜欢
    • 1970-01-01
    • 2011-09-05
    • 2017-06-25
    • 2018-06-09
    • 2021-11-15
    • 2012-08-29
    • 2013-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多