Реализация INotifyPropertyChanged не работает с Entity Framework 4.1 Свойство навигации - PullRequest
0 голосов
/ 20 сентября 2011

Используя EF 4.1, я добавил интерфейс INotifyPropertyChanged, чтобы уведомлять мое представление об изменении свойств.

 public class Department : INotifyPropertyChanged
{
    public Department()
    {
        this.Courses = new ObservableCollection<Course>();
    }

    // Primary key
    public int DepartmentID { get; set; }
    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            RaisePropertyChanged("Name");
        }
    }

    // Navigation property
    public virtual ObservableCollection<Course> Courses { get; private set; }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

public class Course : INotifyPropertyChanged...

В сценарии Master Detail у меня есть комбинация поиска, чтобы изменить Отдел: Когда реализуется INotifyPropertyChanged, свойство отдела не будет обновляться, но при удалении реализации INotifyPropertyChanged из класса Department и Course это будет сделано:

XAML

    <Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <DataGrid 
        AutoGenerateColumns="False" 
        EnableRowVirtualization="True" 
        Height="173" 
        HorizontalAlignment="Left" 
        ItemsSource="{Binding CourceViewSource}" 
        x:Name="departmentDataGrid" 
        RowDetailsVisibilityMode="VisibleWhenSelected" 
        VerticalAlignment="Top" 
        Width="347">
        <DataGrid.Columns>
            <DataGridTextColumn x:Name="CourseID" Binding="{Binding Path=CourseID}" 
                            Header="CourseID" Width="SizeToHeader" />
            <DataGridTextColumn x:Name="nameColumn" Binding="{Binding Path=Title}" 
                            Header="Title" Width="SizeToHeader" />
            <DataGridTextColumn x:Name="nameColumnw" Binding="{Binding Path=Department.Name}" 
                            Header="Department" Width="SizeToHeader" />
        </DataGrid.Columns>
    </DataGrid>

        <ComboBox Grid.Row="1"
                  ItemsSource="{Binding DepartmentLookUp}"
                  SelectedItem="{Binding CourceViewSource/Department}"   />


    <Button Grid.Row="2" Content="Save" Click="Button_Click"/>
</Grid>

Код позади ...

private SchoolEntities _context = new SchoolEntities();
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    public ICollectionView CourceViewSource { get; private set; }
    public ICollectionView DepartmentLookUp { get; private set; }

    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        _context.Departments.Load();     
        _context.Courses.Load();

        DepartmentLookUp = new ListCollectionView(_context.Departments.Local);
        CourceViewSource= new ListCollectionView(_context.Courses.Local);

        RaisePropertyChanged(() => DepartmentLookUp);
        RaisePropertyChanged(() => CourceViewSource);
    }

...

Я включил образец проблемы здесь .

При выборе отдела в деталях, отдел в мастере не обновляется, при изменении% кредита на мастере обновляются данные о кредитах.!

Теперь изменим SchoolModel.cs, чтобы класс Notify не реализовывал интерфейс INotifyPropertyChanged (открытый класс Notify //: INotifyPropertyChanged):

При выборе Отдела в деталях обновляется Отдел в Master DO, при изменении Кредитного% на мастере Кредиты по детали НЕ обновляются.

Я не понимаю, может быть, чего-то не хватает, чтобы заставить обоих работать?

Ответы [ 2 ]

0 голосов
/ 21 сентября 2011

При просмотре загруженного вами кода проблема, похоже, заключается в том, что у вас есть обработчик событий в коде (CourceViewSource_CurrentChanged), который устанавливает свойство Credits, когда CreditPersentage в DataGrid изменяется, но нет counterpart - обработчик события, который устанавливает CreditPersentage при изменении Credits TextBox.

Если ваши отношения между Credits и CreditPersentage всегда в 100 раз, то нет смысла иметь два столбца базы данных для обоих полей. Я бы рассматривал одно из полей как «вычисленное» и «зависимое» от другого и прямо выражал это в модели. В базе данных я бы сохранил только одно из значений. Это может выглядеть так:

public class Course : Notify
{
    //...

    private double _credits; // only one backing field for both properties
    public double Credits
    {
        get { return _credits; }
        set
        {
            _credits = value;
            RaisePropertyChanged(() => Credits);
            RaisePropertyChanged(() => CreditPersentage);
            // notify WPF that also CreditPersentage has changed now
        }
    }

    [NotMapped] // add using System.ComponentModel.DataAnnotations; for this
    public double CreditPersentage
    {
        get { return _credits / 100; }
        set
        {
            _credits = value * 100;
            RaisePropertyChanged(() => Credits);
            // notify WPF that also Credit has changed now
            RaisePropertyChanged(() => CreditPersentage);
        }
    }

    public int DepartmentID { get; set; }

    // also add change notification to Department
    private Department _department;
    public virtual Department Department
    {
        get { return _department; }
        set
        {
            _department = value;
            RaisePropertyChanged(() => Department);
        }
    }
}

Атрибут [NotMapped] гарантирует, что в базе данных нет столбца CreditPersentage. Это свойство просто вычисляется в памяти на основе поля _credits.

Затем вы можете удалить CourceViewSource_CurrentChanged в коде позади. И для вашего текстового поля вы можете добавить UpdateSourceTrigger:

<TextBox Grid.Row="4" Grid.Column="1"
         Text="{Binding Path=CourceViewSource/Credits,
                UpdateSourceTrigger=PropertyChanged}" />

Теперь должна быть возможность редактировать процент в DataGrid (текстовое поле обновляется при написании) и значение Credits в текстовом поле (столбец процент в DataGrid обновляется при написании). И когда вы выбираете новую запись в поле со списком, столбец Отдел в DataGrid обновляется.

0 голосов
/ 21 сентября 2011

Не знаю C # достаточно хорошо, чтобы прокомментировать это, но ниже моя реализация INotifyPropertyChanged в VB.NET.Я не проверяю статус обработчика, а просто поднимаю событие независимо.Никогда не подводил меня.

Public Event PropertyChanged As PropertyChangedEventHandler _
    Implements INotifyPropertyChanged.PropertyChanged

Protected Sub OnPropertyChanged(ByVal info As String)
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
End Sub
...