4

そのようなMarkupExtensionを持っている

public class Extension1 : MarkupExtension
{
    private static int _counter = 0;

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return string.Format("Item {0}", _counter++);
    }
}

そしてこのXAML

<ListBox>
  <ListBoxItem Content="{my:Extension1}"></ListBoxItem>
  <ListBoxItem Content="{my:Extension1}"></ListBoxItem>
  <ListBoxItem Content="{my:Extension1}"></ListBoxItem>
</ListBox>

私はそのようなリストを取得します:

Item 1
Item 2
Item 3

今、私はこのスタイルを使用して同じリストを生成しようとします

<Style TargetType="ListBoxItem">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBoxItem">
                <TextBox Text="{my:Extension1}"></TextBox>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

そしてそのようなXAMLで

<ListBox ItemsSource="{StaticResource data}"></ListBox>

私は得る

Item 0
Item 0
Item 0

したがって、{my:Extension1}は1回だけ評価されます。すべてのアイテムに対して評価される計算プロパティを作成できますか?

4

2 に答える 2

5

文字列の代わりにProvideValueからオブジェクトを返してみてください

Philは正しい方向に進んでいました...実際、マークアップ拡張機能がテンプレートから呼び出された場合は、thisそこから戻る必要があります。ProvideValueこれにより、テンプレートによって生成されたコントロールごとにマークアップ拡張が評価されます。の呼び出しがProvideValueテンプレートからのものであるかどうかを判断するには、ターゲットオブジェクトを確認する必要があります。テンプレートでは、タイプはSystem.Window.SharedDpです。それについてブログに投稿しました。

于 2009-08-23T02:33:29.197 に答える
2

次に、新しいリスト ボックス項目が作成されるたびに、コントロール項目テンプレートの定義が新たに処理されると仮定します。パフォーマンス上の理由から、これは当てはまりません。最初に作成し、その後は毎回複製する方がはるかに高速です。したがって、あなたが望んでいた結果が得られません。拡張機能を呼び出した結果はキャッシュされ、再利用されます。

これを回避するには、静的ではなく動的なものを返す必要があります。文字列ではなく、ProvideValue からオブジェクトを返してみてください。返されたオブジェクト自体にカウンターが含まれ、そのオブジェクトで ToString が呼び出されると、カウンターの文字列バージョンが返されます。

于 2009-03-23T03:03:28.203 に答える