Procedury obsługi zmiany wartości właściwości domeny
W języku specyficznym dla domeny programu Visual Studio po zmianie OnValueChanging()
wartości właściwości domeny metody i OnValueChanged()
są wywoływane w procedurze obsługi właściwości domeny. Aby odpowiedzieć na zmianę, można zastąpić te metody.
Zastąpij metody obsługi właściwości
Każda właściwość domeny języka specyficznego dla domeny jest obsługiwana przez klasę zagnieżdżona wewnątrz nadrzędnej klasy domeny. Jego nazwa jest zgodna z formatem PropertyNamePropertyHandler. Możesz sprawdzić tę klasę obsługi właściwości w pliku Dsl\Generated Code\DomainClasses.cs. W klasie OnValueChanging()
jest wywoływana bezpośrednio przed zmianą wartości i OnValueChanged()
jest wywoływana natychmiast po zmianie wartości.
Załóżmy na przykład, że masz klasę domeny o nazwie Comment
, która ma właściwość domeny ciągu o nazwie i właściwość całkowita o nazwie Text
TextLengthCount
. Aby zawsze TextLengthCount
zawierać długość Text
ciągu, możesz napisać następujący kod w osobnym pliku w projekcie Dsl:
// Domain Class "Comment":
public partial class Comment
{
// Domain Property "Text":
partial class TextPropertyHandler
{
protected override void OnValueChanging(CommentBase element, string oldValue, string newValue)
{
base.OnValueChanging(element, oldValue, newValue);
// To update values outside the Store, write code here.
// Let the transaction manager handle undo:
Store store = element.Store;
if (store.InUndoRedoOrRollback || store.InSerializationTransaction) return;
// Update values in the Store:
this.TextLengthCount = newValue.Length;
}
}
}
Zwróć uwagę na następujące kwestie dotyczące procedur obsługi właściwości:
Metody obsługi właściwości są wywoływane zarówno wtedy, gdy użytkownik wprowadza zmiany w właściwości domeny, a kod programu przypisuje inną wartość do właściwości.
Metody są wywoływane tylko wtedy, gdy wartość rzeczywiście się zmienia. Procedura obsługi nie jest wywoływana, jeśli kod programu przypisuje wartość równą bieżącej wartości.
Właściwości domeny obliczeniowej i niestandardowej domeny magazynu nie mają metod OnValueChanged i OnValueChanging.
Nie można użyć programu obsługi zmian, aby zmodyfikować nową wartość. Jeśli chcesz to zrobić, na przykład, aby ograniczyć wartość do określonego zakresu, zdefiniuj wartość
ChangeRule
.Nie można dodać procedury obsługi zmian do właściwości reprezentującej rolę relacji. Zamiast tego zdefiniuj element
AddRule
iDeleteRule
w klasie relacji. Te reguły są wyzwalane po utworzeniu lub zmianie łączy. Aby uzyskać więcej informacji, zobacz Reguły propagacji zmian w modelu.
Zmiany w i poza sklepem
Metody obsługi właściwości są wywoływane wewnątrz transakcji, która zainicjowała zmianę. W związku z tym można wprowadzić więcej zmian w magazynie bez otwierania nowej transakcji. Zmiany mogą spowodować dodatkowe wywołania programu obsługi.
Gdy transakcja jest cofnięta, ponownie utworzona lub wycofana, nie należy wprowadzać zmian w magazynie, czyli zmian w elementach modelu, relacjach, kształtach, diagramach łączników ani ich właściwościach.
Ponadto zazwyczaj nie można aktualizować wartości podczas ładowania modelu z pliku.
W związku z tym zmiany w modelu powinny być chronione przez test podobny do następującego:
if (!store.InUndoRedoOrRollback && !store. InSerializationTransaction)
{
this.TextLength = ...; // in-store changes
}
Natomiast jeśli program obsługi właściwości propaguje zmiany poza magazynem, na przykład do plików, bazy danych lub zmiennych innych niż magazyn, zawsze należy wprowadzić te zmiany, aby wartości zewnętrzne były aktualizowane, gdy użytkownik wywołuje cofnij lub ponownie.
Anulowanie zmiany
Jeśli chcesz zapobiec zmianie, możesz wycofać bieżącą transakcję. Możesz na przykład upewnić się, że właściwość pozostaje w określonym zakresie.
if (newValue > 10)
{
store.TransactionManager.CurrentTransaction.Rollback();
System.Windows.Forms.MessageBox.Show("Value must be less than 10");
}
Technika alternatywna: właściwości obliczeniowe
W poprzednim przykładzie pokazano, jak można użyć metody OnValueChanged() do propagowania wartości z jednej właściwości domeny do innej. Każda właściwość ma własną wartość przechowywaną.
Zamiast tego można rozważyć zdefiniowanie właściwości pochodnej jako właściwości Calculated. W takim przypadku właściwość nie ma własnego magazynu i definiuje funkcję, gdy jej wartość jest wymagana. Aby uzyskać więcej informacji, zobacz Właściwości obliczeniowe i niestandardowego magazynu.
Zamiast poprzedniego przykładu można ustawić pole TextLengthCount
Rodzaj do obliczenia w definicji DSL. Należy podać własną metodę Get dla tej właściwości domeny. Metoda Get zwróci bieżącą długość Text
ciągu.
Jednak potencjalną wadą właściwości obliczeniowych jest to, że wyrażenie jest obliczane za każdym razem, gdy jest używana wartość, co może stanowić problem z wydajnością. Ponadto nie ma właściwości OnValueChanging() i OnValueChanged().
Alternatywna technika: Zmienianie reguł
Jeśli zdefiniujesz metodę ChangeRule, zostanie ona wykonana na końcu transakcji, w której wartość właściwości ulegnie zmianie. Aby uzyskać więcej informacji, zobacz Reguły propagacji zmian w modelu.
Jeśli w jednej transakcji zostanie wprowadzonych kilka zmian, funkcja ChangeRule zostanie wykonana po zakończeniu ich wszystkich. Natomiast wartość OnValue... metody są wykonywane, gdy niektóre zmiany nie zostały wykonane. W zależności od tego, co chcesz osiągnąć, może to spowodować, że zmianarule będzie bardziej odpowiednia.
Możesz również użyć metody ChangeRule, aby dostosować nową wartość właściwości, aby zachować ją w określonym zakresie.
Ostrzeżenie
Jeśli reguła wprowadza zmiany w zawartości magazynu, mogą zostać wyzwolone inne reguły i procedury obsługi właściwości. Jeśli reguła zmieni właściwość, która ją wyzwoli, zostanie wywołana ponownie. Musisz upewnić się, że definicje reguł nie powodują nieskończonego wyzwalania.
using Microsoft.VisualStudio.Modeling;
...
// Change rule on the domain class Comment:
[RuleOn(typeof(Comment), FireTime = TimeToFire.TopLevelCommit)]
class MyCommentTrimRule : ChangeRule
{
public override void
ElementPropertyChanged(ElementPropertyChangedEventArgs e)
{
base.ElementPropertyChanged(e);
Comment comment = e.ModelElement as Comment;
if (comment.Text.StartsWith(" ") || comment.Text.EndsWith(" "))
comment.Text = comment.Text.Trim();
// If changed, rule will trigger again.
}
}
// Register the rule:
public partial class MyDomainModel
{
protected override Type[] GetCustomDomainModelTypes()
{ return new Type[] { typeof(MyCommentTrimRule) };
}
}
Przykład
opis
Poniższy przykład zastępuje procedurę obsługi właściwości właściwości właściwości i powiadamia użytkownika o zmianie właściwości klasy ExampleElement
domeny.
Kod
using DslModeling = global::Microsoft.VisualStudio.Modeling;
using DslDesign = global::Microsoft.VisualStudio.Modeling.Design;
namespace msft.FieldChangeSample
{
public partial class ExampleElement
{
internal sealed partial class NamePropertyHandler
{
protected override void OnValueChanged(ExampleElement element,
string oldValue, string newValue)
{
if (!this.Store.InUndoRedoOrRollback)
{
// make in-store changes here...
}
// This part is called even in undo:
System.Windows.Forms.MessageBox.Show("Value Has Changed");
base.OnValueChanged(element, oldValue, newValue);
}
}
}
}