0

I have a DataGrid with a DataGridCheckBoxColumn and others. The DataGrid ItemSource is mapped to a ObservableCollection that contains rows of Tasks. The Task class includes properties like "ID", "IsScheduled", "IsScheduled_Date", "IsScheduled_EditorID", Etc. I am trying to figure how to make the one DataGridCheckBoxColumn field (IsScheduled) also save the date (IsScheduled_Date) and who made the change (IsScheduled_EditorID) when checked.

(1) I have tried to make this save the extra data using multibinding, but my efforts have so far failed. You can see follow my progress with solving a similar issue Here.

(2) I have tried having the DataGrid CellEditEnding event save the extra data but it ended up committing the extra data before the IsScheduled data was committed and caused troubles whenever the row and/or cell edit was canceled.

(3) I have tried listening to the property change event in my Task class and assigning the additional changes there. This seemed to work fine until I realized that when the data was first loaded it cause a change event that overwrote any earlier changes.

Added Information


The Task class is an Entity Framework Class that was generated from a DB. I was listening to the OnIscheduledChanged event and making the necessary changes because when I did it in the generated class it was always overwritten.

More Info


There seems to be some confusion about the Task class. As I stated it is generated by the Entity Framework and a breakpoint shows the setters being called on load... Overwriting the change. Not to mention any custom code being overwritten everytime the code regenerates.

    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
    [DataMemberAttribute()]
    public global::System.Boolean IsScheduled
    {
        get
        {
            return _IsScheduled;
        }
        set
        {
            OnIsScheduledChanging(value);
            ReportPropertyChanging("IsScheduled");
            _IsScheduled = StructuralObject.SetValidValue(value);
            ReportPropertyChanged("IsScheduled");
            OnIsScheduledChanged();
        }
    }
    private global::System.Boolean _IsScheduled;
    partial void OnIsScheduledChanging(global::System.Boolean value);
    partial void OnIsScheduledChanged();

Any Ideas?

Community
  • 1
  • 1
Net Dev
  • 416
  • 4
  • 21
  • If these properties are so interconnected, why is not this logic implemented inside IsScheduled property setter? – Pavel Voronin Sep 04 '12 at 15:46
  • I think the 3d way is Ok. I'd rather look for the solution for correct initialization. – Pavel Voronin Sep 04 '12 at 15:57
  • The properties weren't connected in the setter. I was listening for the change event for IsScheduled in a partial class to the Task class (Which was generated by Entity Framework) – Net Dev Sep 04 '12 at 16:29
  • You can create some proxy wich will stand as a ViewModel for the Task class and what Blam offers you if I understand him correctly. But that costs extra code. For this purpose you can use http://automapper.org/ By the way, some developers insist on not pushing pure data object to the View but creating DataTransferObjects. – Pavel Voronin Sep 04 '12 at 16:47
  • I am not so sure about the proxy you are talking about and what I interpreted from his post was a standard class with property change notification held in a collection with collection change notification. Which basically was my option (3). The only difference being was in mine I received rows from the DB that call the setter right off the bat. Instead of `xxxs.Add(new xxx("Mike"));` It would be more like `xxx newxxx1("Mike"); newxxx1.isChecked = true; xxxs.Add(newxxx1);` with the framework making the call. (and calling the setter which overwrites the date etc.) – Net Dev Sep 04 '12 at 17:59
  • I meant `xxx newxxx1 = new xxx("Mike");` and not `xxx newxxx1("Mike");` – Net Dev Sep 04 '12 at 18:25

2 Answers2

0

Do it in the class

public partial class MainWindow : Window 
    {
        public ObservableCollection<xxx> xxxs { get; private set; }

        public MainWindow()
        {
            xxxs = new ObservableCollection<xxx>();
            xxxs.Add(new xxx("Mike", false));
            xxxs.Add(new xxx("Sarah", true));

            InitializeComponent();
        }

        public class xxx: INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            private void NotifyPropertyChanged(String info)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(info));
                }
            }

            private bool isChecked;
            public bool IsChecked
            {
                get { return isChecked; }
                set
                {
                    if (isChecked == value) return;
                    if (value) FirstName = DateTime.Now.ToString(); else FirstName = string.Empty;
                    // update db
                    isChecked = value;
                    NotifyPropertyChanged("FirstName");
                }
            }
            public string FirstName { get; private set; }
            public xxx(string firstName, bool _isChecked) { FirstName = firstName; isChecked = _isChecked; }
        }
    }

        DataContext="{Binding RelativeSource={RelativeSource self}}"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid x:Name="MyGrid" ItemsSource="{Binding Path=xxxs}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridCheckBoxColumn Header="CheckBox" Binding="{Binding IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                <DataGridTextColumn Header="Text"  Binding="{Binding FirstName, Mode=OneWay}"/>
            </DataGrid.Columns>
        </DataGrid> 
paparazzo
  • 44,497
  • 23
  • 105
  • 176
  • (I added some info above about the Task Class) The Task class IsScheduled is called when getting the information from the database. In Option (3) as I described above my Setter like your Setter will cause the values to be overwritten if IsChecked comes in from the DB as true. – Net Dev Sep 04 '12 at 16:28
  • Come on apply yourself. Read the value from the DB and assign it in the constructor. – paparazzo Sep 04 '12 at 19:08
  • How can there be changes earlier than when the data was loaded? – paparazzo Sep 04 '12 at 19:40
  • I don't think it is constructive to degrade someones efforts. – Net Dev Sep 05 '12 at 11:36
  • Also, It is changing at load is the issue. – Net Dev Sep 07 '12 at 18:24
0

I ended up creating a ViewModel class for the entity model that exposed the same property. I bound the DataGrid ItemSource to a list of the wrapped Task Models (e.g. below). [Obviously this is quick example class to show the property and would need property notification to work properly]

Class TaskViewModel
{
    private Task task;
    public Boolean IsScheduled
    {
        get
        {
            return task.IsScheduled;
        }
        set
        {
            this.task.IsScheduled = value;
            this.task.IsScheduledDate = Date.Now();
        }

    TaskViewModel(Task task)
    {
       this.task = task;
    }
}
Net Dev
  • 416
  • 4
  • 21