2011-02-04 21 views
3

私が作業しているプロジェクトのクラスのデリゲートに問題があります。このクラスは、ラベルと値の両方を受け入れるGUIコンポーネントです。ここでのアイデアは、ユーザーがラベルを指定して、その値が更新されるたびにGUIコンポーネントが表示されるように、どこからでも(特にその値のToStringメソッド)値をリンクできることです。これは、それが設定されている方法の基本である:デリゲートの詳細

public delegate string GUIValue(); 

public class GUIComponent 
{ 
    GUIValue value = null; // The value linked in 
    string label = "";  // The label for the value 
    string text = "";   // The label and value appended together 

    public GUIComponent(string Text, GUIValue Value) 
    { 
     this.text = Text; 
     this.value += Value; 
    } 

    public void Update() 
    { 
     this.text = this.label + this.value(); 
    } 
} 

そして私は、コードが正しくコンパイル、およびコンポーネントが表示を行い、および初期値を表示し

GUIComponent component = new GUIComponent("Label: ", 
           new GUIValue(this.attribute.ToString)); 

このようにそれを呼び出しますただし、属性値が変更されるたびに更新されることはありません。

私の質問は、私が最初に正しい設定をしているかどうかであり、もしそうなら、なぜそれが動作しないのかということです。私の最初の考えは、引数をとらないので、ToStringメソッドによる最初の値の返りを受け付けるだけですが、誰でもそれを確認できますか?

+0

「更新」メソッドはいつ呼びますか? – Justin

+0

更新メソッドは、フレームごとにゲームコードによって自動的に呼び出されます。 – shmeeps

答えて

1

このコード:

new GUIValue(this.attribute.ToString) 

メソッドは、属性が変わるたびに呼ばれることはありません。デリゲートを保存し、誰かが "属性"を変更するたびに呼び出す必要があります。次のようなもの:

private event GUIValue attributeChanged =() => this.attribute.ToString(); 

private String attribute; 

// This is a property that sets the value of attribute 
public String Attribute { get { return attribute; } set { attribute = value; attributeChanged(); } } 

// Now you can initialize the component using: 
// GUIComponent component = new GUIComponent("Label: ", this.attributeChanged); 
+0

これは完璧に働いた、ありがとう! – shmeeps

1

代理人を呼び出す必要があります。
あなたが持っているものはvaluethis.attribute.ToStringメソッドを参照しています。

これは、this.value()を呼び出すと、その関数が呼び出されることを意味します。

this.attributeの値を変更すると、別の値を含む別のオブジェクトを参照することによって、おそらくそのようになりました。
あなたが経験していることは、update()を呼び出すたびに古い値が表示されることです。これは、デリゲートを介して参照を保持しているため、古いオブジェクトがガベージコレクタによって破棄されないためです。

属性の値を変更すると、GUIデリゲートには古いオブジェクトのメソッドが保持され、新しいオブジェクトは保持されません。

1

あなたはその半分を持っています。実際には値が実際に変更されたGUIValueデリゲートとして与えられたメソッドを持つクラスがあれば、あなたのGuiComponentは最初に値を取得することはできますが、再取得するように指示されています。何かが起こったことを他のオブジェクトに伝える通常の方法は、イベントが発生したときに実行されるデリゲートを渡して他のオブジェクトを「購読する」イベントです。ここで

は、私はあなたのコードを構造化する方法をです:今

public interface IHaveAValueYouNeed 
{ 
    string ValueGetter(); 
    event EventArgs ValueChanged; 
} 

public class GUIComponent 
{ 
    public delegate string ValueGetter(); 

    ValueGetter getter; // The value linked in 
    string label = "";  // The label for the value 
    string text = "";   // The label and value appended together 

    public GUIComponent(string Text, IHaveAValueYouNeed getter) 
    { 
     this.text = Text; 
     this.getter += getter.ValueGetter; 
     getter.ValueChanged += ValueUpdatedHandler; 
    } 

    public void Update() 
    { 
     this.text = this.label + this.value(); 
    } 

    public void ValueUpdatedHandler(object sender, EventArgs e) 
    { 
     Update(); 
    } 
} 

あなたがコンポーネントへのインタフェースの実装を渡す際に、コンポーネントは、そのValueGetterへの参照を取得し、インスタンスに代表団を交換し、そのイベントを購読する。 IHaveAValueYouNeedの実装では、値が変更されたとき(直接的に、またはゲッタによって生成された計算値を変更するものが変更されたとき)にイベントを発生させる必要があります。このようにして、値を制御しているオブジェクトは、値が変更されたことに関心を持つ人々に伝えることができます。

1

なぜToStringを使用しないのですか?

public class GUIComponent 
{ 
    object value = null; // The value linked in 
    string label = "";  // The label for the value 
    string text = "";   // The label and value appended together 

    public GUIComponent(string Text, object Value) 
    { 
     this.text = Text; 
     this.value = Value; 
    } 

    public void Update() 
    { 
     this.text = this.label + this.value.ToString(); 
    } 
}