Привязка цвета строки WPF Datagrid к свойству элемента внутри наблюдаемой коллекции

Я надеюсь, что кто-то может помочь мне в этом. У меня есть приложение MVVMLight, в котором у меня есть наблюдаемая коллекция объектов в моей модели представления, привязанная к свойству ItemsSource WPF DataGrid. Теперь я хочу изменить цвет фона строки всякий раз, когда конкретное значение под названием «TaskAssignmentStatus» изменяется для любого элемента внутри наблюдаемой коллекции.

Однако я получаю ошибку синтаксического анализа XAML следующим образом:

{«Операция недопустима при использовании ItemsSource. Доступ и изменение элементов с помощью ItemsControl.ItemsSource вместо.»}

Я прочитал все, что я могу найти относительно этой ошибки, но я не смог увидеть, как применить все, что я узнал из ответов, данных до сих пор, к моей конкретной ситуации. Я очень новичок в WPF и databiding, поэтому любая помощь была бы очень признательна. Спасибо!

Соответствующий код с моей точки зрения-модель выглядит следующим образом:

//Contains the actual tasks on the currently selected team member's    
//work-list
public ObservableCollection<WorklistTask> TasksForSelectedTeamMember
{
    get { return _tasksForSelectedTeamMember; }
    set
    {
        if (value != null)
        {
            _tasksForSelectedTeamMember = value;
            RaisePropertyChanged("TasksForSelectedTeamMember");
        }
    }
}

Вот определение класса для типов внутри моей наблюдаемой коллекции в модели представления:

public class WorklistTask : ICloneable
{
    #region Fields

    private int _taskId;
    private int _activityId;
    private string _activityName;
    private string _activityStatus;
    private string _taskAssignDate;
    private string _activityStartDate;
    private string _activityDueDate;
    private string _caseStartDate;
    private string _caseDueDate;
    private int _caseId;
    private string _caseType;

    //an enum which indicates whether or not the task has been reassigned 
    private WorkListTaskAssignmentStatus _taskAssignmentStatus;

    private int _sourceTaskId;
    private bool _selectedByUserInUI = false;


    #endregion

    #region Constructors

    public WorklistTask() { }

    #endregion

    #region Properties

    [DisplayName("Task Assignment Status")]
    public WorkListTaskAssignmentStatus TaskAssignmentStatus
    {
        get { return _taskAssignmentStatus; }
        set { _taskAssignmentStatus = value; }
    }


    public int TaskId
    {
        get { return _taskId; }
        set { _taskId = value; }
    }


    public int ActivityId
    {
        get { return _activityId; }
        set { _activityId = value; }
    }

    [DisplayName("Activity Name")]
    public string ActivityName
    {
        get { return _activityName; }
        set { _activityName = value; }
    }
    [DisplayName("Activity Status")]
    public string ActivityStatus
    {
        get { return _activityStatus; }
        set { _activityStatus = value; }
    }
    [DisplayName("Task Assigned Date")]
    public string TaskAssignDate
    {
        get { return _taskAssignDate; }
        set { _taskAssignDate = value; }
    }
    [DisplayName("Activity Start Date")]
    public string ActivityStartDate
    {
        get { return _activityStartDate; }
        set { _activityStartDate = value; }
    }
    [DisplayName("Activity Due Date")]
    public string ActivityDueDate
    {
        get { return _activityDueDate; }
        set { _activityDueDate = value; }
    }
    [DisplayName("Case Start Date")]
    public string CaseStartDate
    {
        get { return _caseStartDate; }
        set { _caseStartDate = value; }
    }
    [DisplayName("Case Due Date")]
    public string CaseDueDate
    {
        get { return _caseDueDate; }
        set { _caseDueDate = value; }
    }

    [DisplayName("Case Id")]
    public int CaseId
    {
        get { return _caseId; }
        set { _caseId = value; }
    }
    [DisplayName("Case Type")]
    public string CaseType
    {
        get { return _caseType; }
        set { _caseType = value; }
    }


    public int SourceTaskId
    {
        get { return _sourceTaskId; }
        set { _sourceTaskId = value; }
    }

    public bool SelectedByUserInUI
    {
        get { return _selectedByUserInUI; }
        set { _selectedByUserInUI = value; }
    }

    #endregion

    #region Methods

    public object Clone()
    {
        WorklistTask newWorklistTask = (WorklistTask)this.MemberwiseClone();
        newWorklistTask.ActivityName = string.Copy(ActivityName);
        newWorklistTask.ActivityStatus = string.Copy(ActivityStatus);
        newWorklistTask.TaskAssignDate = string.Copy(TaskAssignDate);
        newWorklistTask.ActivityStartDate = string.Copy(ActivityStartDate);
        newWorklistTask.ActivityDueDate = string.Copy(ActivityDueDate);
        newWorklistTask.CaseStartDate = string.Copy(CaseStartDate);
        newWorklistTask.CaseDueDate = string.Copy(CaseDueDate);
        newWorklistTask.CaseType = string.Copy(CaseType);

        return newWorklistTask;
    }

    #endregion
}

Вот перечисление:

public enum WorkListTaskAssignmentStatus
{
    Automatic,
    Added,
    Removed,
    DeleteLocal
}

Вот XAML для datagrid, который я пытаюсь отформатировать:

<DataGrid x_Name="WorklistOfSelectedTeamMember"
          ItemsSource="{Binding TasksForSelectedTeamMember, Mode=TwoWay,   
          UpdateSourceTrigger=PropertyChanged}"                 
          AutoGeneratingColumn="GenerateColumnsForWorklist"                                   
          IsReadOnly="True"
          FontWeight="Normal"
          FontSize="13" 
          SelectionMode="Extended"
          AlternatingRowBackground="LightGray"
          Grid.Column="0"
          Grid.ColumnSpan="2"
          Grid.Row="3" 
          Margin="0,0,5,0"
          HorizontalScrollBarVisibility="Auto"
          Height="150"
          Style="{StaticResource DataGridColoring}">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <cmd:EventToCommand Command="{Binding 
                WorklistTaskSelectionChangedCommand}" 
                CommandParameter="{Binding SelectedItems, 
                ElementName=WorklistOfSelectedTeamMember}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
        <Style TargetType="DataGridRow">
            <Style.Triggers>
                <DataTrigger Binding="{Binding TaskAssignmentStatus}" 
                 Value="Automatic">  
                    <Setter Property="Background" Value="Transparent"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding TaskAssignmentStatus}" 
                 Value="Removed">
                    <Setter Property="Background" Value="#C4FF0000"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding TaskAssignmentStatus}" 
                 Value="Added">
                     <Setter Property="Background" Value="#00FF7F"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding TaskAssignmentStatus}" 
                 Value="DeleteLocal">
                     <Setter Property="Background" Value="#00FFFFFF"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>                            
</DataGrid>

2 ответа

  1. Ваш код для изменения цвета фона кажется просто прекрасным, и он должен работать.

    Строка ошибки, которую вы упомянули, не об этом, это означает, что вы пытаетесь каким-то образом добавить / удалить элементы непосредственно из свойства ItemsSource DataGrid DataGrid.ItemsSource

    Нельзя использовать ItemsSource для непосредственного изменения элементов, вместо этого необходимо использовать коллекцию.

  2. Чтобы избавиться от ошибки, добавьте неявный стиль строк в словарь ресурсов DataGrid:

    <DataGrid x_Name="WorklistOfSelectedTeamMember"
              ItemsSource="{Binding TasksForSelectedTeamMember, Mode=TwoWay,   
              UpdateSourceTrigger=PropertyChanged}"                                                   
              IsReadOnly="True"
              FontWeight="Normal"
              FontSize="13" 
              SelectionMode="Extended"
              AlternatingRowBackground="LightGray"
              Grid.Column="0"
              Grid.ColumnSpan="2"
              Grid.Row="3" 
              Margin="0,0,5,0"
              HorizontalScrollBarVisibility="Auto"
              Height="150">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <cmd:EventToCommand Command="{Binding 
                    WorklistTaskSelectionChangedCommand}" 
                    CommandParameter="{Binding SelectedItems, 
                    ElementName=WorklistOfSelectedTeamMember}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
        <DataGrid.Resources>
            <Style TargetType="DataGridRow">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding TaskAssignmentStatus}" 
                     Value="Automatic">
                        <Setter Property="Background" Value="Transparent"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding TaskAssignmentStatus}" 
                     Value="Removed">
                        <Setter Property="Background" Value="#C4FF0000"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding TaskAssignmentStatus}" 
                     Value="Added">
                        <Setter Property="Background" Value="#00FF7F"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding TaskAssignmentStatus}" 
                     Value="DeleteLocal">
                        <Setter Property="Background" Value="#00FFFFFF"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.Resources>
    </DataGrid>
    

    Также обратите внимание, что если требуется изменить цвет фона строки при установке значения свойства TaskAssignmentStatus элемента в коллекции ObservableCollection на новое значение динамически во время выполнения, класс WorklistTask должен реализовать интерфейс INotifyPropertyChanged и вызвать событие PropertyChanged в задателе свойства TaskAssignmentStatus.