我試圖找到一種更清潔的替代方案(即Scala的慣用方法),以便在WPF/silverlight數據綁定中使用數據綁定 - 即實現INotifyPropertyChanged時看到的那種東西。首先,一些背景:慣用屬性更改scala中的通知?
在.net WPF或silverlight應用程序中,您有雙向數據綁定的概念(即將UI的某些元素的值綁定到DataContext的.net屬性中改變UI元素的方式會影響屬性,反之亦然,一種方法是在你的DataContext中實現INotifyPropertyChanged接口,不幸的是,這會爲你添加到「ModelView」的任何屬性引入很多樣板代碼「類型下面是它可能看起來在斯卡拉:
trait IDrawable extends INotifyPropertyChanged
{
protected var drawOrder : Int = 0
def DrawOrder : Int = drawOrder
def DrawOrder_=(value : Int) {
if(drawOrder != value) {
drawOrder = value
OnPropertyChanged("DrawOrder")
}
}
protected var visible : Boolean = true
def Visible : Boolean = visible
def Visible_=(value: Boolean) = {
if(visible != value) {
visible = value
OnPropertyChanged("Visible")
}
}
def Mutate() : Unit = {
if(Visible) {
DrawOrder += 1 // Should trigger the PropertyChanged "Event" of INotifyPropertyChanged trait
}
}
}
出於節省空間的考慮,我們假設INotifyPropertyChanged的類型是管理型的回調(AnyRef,字符串列表的特質)=> Unit,並且OnPropertyChanged是調用所有這些回調的方法,傳遞「this」作爲AnyRef和傳入的String)。這只是C#中的一個事件。
你可以立即看到問題:這是大量的樣板代碼只有兩個屬性。我一直想寫這樣的事情,而不是:
trait IDrawable
{
val Visible = new ObservableProperty[Boolean]('Visible, true)
val DrawOrder = new ObservableProperty[Int]('DrawOrder, 0)
def Mutate() : Unit = {
if(Visible) {
DrawOrder += 1 // Should trigger the PropertyChanged "Event" of ObservableProperty class
}
}
}
我知道,我可以很容易地把它寫這樣的,如果ObservableProperty [T]具有價值/ VALUE_ =方法(這是我使用的方法現在):
trait IDrawable {
// on a side note, is there some way to get a Symbol representing the Visible field
// on the following line, instead of hard-coding it in the ObservableProperty
// constructor?
val Visible = new ObservableProperty[Boolean]('Visible, true)
val DrawOrder = new ObservableProperty[Int]('DrawOrder, 0)
def Mutate() : Unit = {
if(Visible.Value) {
DrawOrder.Value += 1
}
}
}
// given this implementation of ObservableProperty[T] in my library
// note: IEvent, Event, and EventArgs are classes in my library for
// handling lists of callbacks - they work similarly to events in C#
class PropertyChangedEventArgs(val PropertyName: Symbol) extends EventArgs("")
class ObservableProperty[T](val PropertyName: Symbol, private var value: T) {
protected val propertyChanged = new Event[PropertyChangedEventArgs]
def PropertyChanged: IEvent[PropertyChangedEventArgs] = propertyChanged
def Value = value;
def Value_=(value: T) {
if(this.value != value) {
this.value = value
propertyChanged(this, new PropertyChangedEventArgs(PropertyName))
}
}
}
但是,有沒有辦法使用implicits或斯卡拉的一些其他功能/成語,使ObservableProperty實例功能,好像他們是普通的「屬性」,在斯卡拉實施的第一個版本,而無需調用價值的方法?我能想到的唯一的另一件事是這樣的,這是比任何上述兩個版本的更詳細,但仍比原來少了冗長:
trait IDrawable {
private val visible = new ObservableProperty[Boolean]('Visible, false)
def Visible = visible.Value
def Visible_=(value: Boolean): Unit = { visible.Value = value }
private val drawOrder = new ObservableProperty[Int]('DrawOrder, 0)
def DrawOrder = drawOrder.Value
def DrawOrder_=(value: Int): Unit = { drawOrder.Value = value }
def Mutate() : Unit = {
if(Visible) {
DrawOrder += 1
}
}
}
本文可能會讓您感興趣:http://www.ganguin.net/frp2d.pdf – 2010-05-26 19:45:30
另請參閱http:// stackoverflow。com/questions/1054179/functional-reactive-programming-in-scala目前爲止沒有成功。不幸的是,這是斯卡拉糟糕的設計決定。 – thSoft 2010-05-27 09:03:52