2010-03-17 2 views
2

У меня есть форма, привязанная к объекту, и когда пользователь пытается оставить форму, я хочу предупредить их, если что-либо в форме было изменено и предложит им сохранить. Мой вопрос в том, есть ли способ достичь этого без реализации IComparar для всех моих классов в связанном объекте? Я думал, есть ли способ, с помощью которого я могу сериализовать свой объект при загрузке формы, и сделать простое сравнение с объектом изменения, который также будет сериализован. Что-то вроде сравнения строк.Проверить изменение состояния объектов с помощью сериализации?

Надежда, что имеет смысл,

Благодаря

+0

Спасибо за все ответы, я знаю метод IsDirty, но мне просто интересно, есть ли другой способ сделать это. Теперь мне интересно, если бы я сериализовал объекты в XML, это было бы более надежным методом. – sev7n

ответ

0

Чтобы сделать то, что вы пытаетесь сделать, возможно, существует гораздо более простой метод: используйте «измененный» флаг или событие.

Вы можете, если нужно, каскадировать это на многих уровнях пользовательских элементов управления. Просто объявите событие следующим образом:

public class MyControl : Control 
{ 
    public MyControl() 
    { 
     InitializeComponent(); 
     textBox1.TextChanged += BubbleModified; 
     // etc. 
    } 

    protected void BubbleModified(object sender, EventArgs e) 
    { 
     OnModified(e); 
    } 

    protected void OnModified(EventArgs e) 
    { 
     var handler = Modified; 
     if (handler != null) 
      handler(this, e); 
    } 

    [Category("Behavior")] 
    [Description("Occurs when data on the control is modified.")] 
    public event EventHandler Modified; 
} 

Затем, на любом уровне, который вам нужно проверить на предмет изменений, зацепите все события.

public class MainForm : Form 
{ 
    private bool isDataModified; 

    public MainForm() 
    { 
     InitializeComponent(); 

     textBox1.TextChanged += DataModified; 
     textBox2.TextChanged += DataModified; 
     // etc. 
     userControl1.Modified += DataModified; 
     userControl2.Modified += DataModified; 
     // etc. 
    } 

    private void DataModified(object sender, EventArgs e) 
    { 
     isDataModified = true; 
    } 
} 

Тогда все, что вам нужно сделать, это проверить (и сброс) на isDataModified флаг соответственно.

Это действительно не так много работы, конечно, проще, чем обеспечить, чтобы INotifyPropertyChanged был реализован для каждого объекта на графике. Помните, что это форма, вам все равно, что объект изменен, вам небезразлично, если пользователь внес изменения, и для этого вы хотите проверить изменения, внесенные с помощью элементов управления.

Да, это не идеально - вы все еще сталкиваетесь с незначительной неприятностью в связи с сообщением о том, что данные были изменены, даже когда пользователь что-то меняет, а затем меняет его.Но я не думаю, что когда-либо слышал об этом жалобу, и использование сериализации в качестве метода сравнения просто не является надежным. То, что вам действительно нужно сделать, если вы хотите устранить избыточное подтверждение сохранения, переопределяет метод Equals каждого объекта на графике и реализует действительную операцию равенства по значению. Или, если вы не хотите сохранять копию старого графика, используйте функцию генерирования контрольной суммы (коллизии возможны, но очень маловероятны).

Но я бы просто придерживался флага. Не пытайтесь обмануть свой путь от написания проверок равенства. На самом деле это похоже на попытку написать автоматический метод глубокого клонирования; вы можете попробовать, но все, что вы придумали, будет сломан иногда.

1

Это было asked before, в виде сравнения 2 деревья объектов с помощью сериализации.
Ответ был: он не является надежным, есть примеры примеров равных объектов, генерирующих разные сериализованные тексты/данные.

+0

Звучит так, будто выбранный сериализатор сломан. Мне было бы интересно увидеть это «раньше». –

+0

@marc: см. Править. –

+0

@Marc Gravell: до тех пор, пока классы имеют возможность контролировать как свои операции с равенством, так и их сериализованные представления, это никогда не будет полностью надежным, даже если сериализатор работает отлично. – Aaronaught

1

Если вы будете следовать шаблону регулярного, что люди используют при реализации INotifyPropertyChanged, то все это занимает еще несколько строк кода для реализации IsDirty (или IsChanged) флаг на объекте данных.

Прежде всего, создать базовый класс, который реализует основы, и реальный класс данных, производные от него:

public class BaseDataObject : INotifyPropertyChanged 
{ 

    public bool IsDirty 
    { 
     get { return _isDirty; } 
     protected set { _isDirty = value; } 
    } 

    protected void OnPropertyChanged(string propertyName) 
    { 
     _isDirty = true; 

     if (this.PropertyChanged != null) 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    #endregion 

    private bool _isDirty; 
} 


public class MyRealDataObject : BaseDataObject 
{ 
    public int MyIntProperty 
    { 
     get { return _myIntProperty; } 
     set 
     { 
      bool changed = _myIntProperty != value; 
      if (changed) 
      { 
       _myIntProperty = value; 
       OnPropertyChanged("MyIntProperty"); 
      } 
     } 
    } 

    private int _myIntProperty; 
} 

Теперь всякий раз, когда уведомлению изменение свойств, IsDirty флага объекта данных будет установлено правда. Чтобы проверить изменения, все, что вам нужно сделать, это перечислить коллекцию объектов и проверить флаг IsDirty. Если вы умны, вы можете сделать это с утверждением LINQ:

bool changesMade = MyDataObjectCollection.Any(p => p.IsDirty == true).Count() > 0; 

... or .... 

bool changesMade = MyDataObjectCollection.Count(p => p.IsDirty == true) > 0; 

Если ваши данные объекты не находятся в хорошей коллекции, вы просто должны повторять их вручную. Конечно, описанная выше схема может быть реорганизована несколькими разными способами (эй, возможно, вы даже не используете INotifyPropertyChanged, потому что вы не привязываете данные к элементам пользовательского интерфейса), но это дает вам хороший стартовый пример того, как продвигать вы хотите.

Смежные вопросы