質問

I have a CommentsData class and this is used to load, manipulate and save values in a DataGrid. I want to make the Status field in the class shown as a dropdown in the grid. The Comment values need to be populated one time only. I have tried many variations but this does not work. The combo is blank. 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.

Here is the Xaml for the Grid (Updated 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>

Here is the code for the CommentData class (Updated 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;
    }
}

Here is the code where the comments list is initialized

private List<CommentsData> _commentsList;

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

}

The above code is working Thanks to all the feedback

役に立ちましたか?

解決

As stated on MSDN article about DataGridComboBoxColumn to populate the drop-down list, you must first set the ItemsSource property for the ComboBox by using one of the following options:

  • A static resource.
  • An x:Static code entity.
  • An inline collection of ComboBoxItem types.

If you want to bind ComboBox.ItemsSource to object property, it`s easier to use DataGridTemplateColumn like this:

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

他のヒント

There are a few things that I see missing from your code

First off, your class doesn't implement INotifyPropertyChanged. That means, if a property changes on CommentData, it doesn't tell the UI that is has changed, so the UI doesn't update to display the new value.

Second, you are telling your ComboBox that there is a property called Status on each item, and use it as the ComboBoxItem.Value, however this property does not exist on StatusValue. Change it to refer to UserStatus, which is a valid property on StatusValue.

SelectedValuePath="UserStatus"

And last of all, you really shouldn't be re-creating the ComboBox items on each item. Instead, create the collection somewhere further up in the ViewModel hierarchy, or make it a static resource.

For example, if the class which contains your collection of CommentsData also contained your collection of StatusValues, you could use a RelativeSource binding to bind to it like this:

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

Here is what I would use instead your DataGridComboboxColumn:

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

Also CommentsData.Status should be of type StatusValue, not string, so that you can bind the SelectedItem on it.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top