11

コンテンツを保持するカスタム プロパティを宣言したカスタム パネルがあります (コンテンツに Children を使用したくありません)。

[ContentProperty(Name = "PanelContent")]
public class CustomPanel : Panel
{
    public static readonly DependencyProperty PanelContentProperty =
       DependencyProperty.Register("PanelContent", 
       typeof(Collection<UIElement>), typeof(CustomPanel), 
       new PropertyMetadata(new Collection<UIElement>(), null));

    public Collection<UIElement> PanelContent
    {
        get
        {
            return (Collection<UIElement>)GetValue(PanelContentProperty);
        }
    }
}

これは、次のように使用すると完全に機能します。

<CustomPanel>
   <TextBlock>A</TextBlock>
   <TextBlock>B</TextBlock>
</CustomPanel>

しかし、パネルを ItemsControl 内の ItemsPanelTemplate として使用したい場合、ContentProperty 属性は無視され、すべてをPanelContentコレクションではなくChildrenコレクションに追加します。

<ItemsControl ItemTemplate="{StaticResource ReviewTemplate}" ItemsSource="{Binding Reviews}">
   <ItemsControl.ItemsPanel>
      <ItemsPanelTemplate>
         <CustomPanel></CustomPanel>
      </ItemsPanelTemplate>
   </ItemsControl.ItemsPanel>
</ItemsControl>

これは機能する方法ではありません。ドキュメントによると:

ItemsPanelTemplate オブジェクト要素には、項目のルート要素として機能する FrameworkElement 派生クラスを 1 つだけ含める必要があります。ほとんどの場合、これは Panel 派生クラスです。展開されたテンプレートは実現されたアイテムの親として機能し、通常は複数のアイテムがあります。したがって、ItemsPanelTemplate の目的のルート要素の XAML コンテンツ プロパティは、Panel.Children と同様にコレクションをサポートする必要があります。

4

3 に答える 3

2

このタスクを担当する Panel の GenerateChildren メソッドは ( ILSpyで見られるように) 次のようになります。

internal virtual void GenerateChildren()
{
    IItemContainerGenerator itemContainerGenerator = this._itemContainerGenerator;
    if (itemContainerGenerator != null)
    {
        using (itemContainerGenerator.StartAt(new GeneratorPosition(-1, 0), GeneratorDirection.Forward))
        {
            UIElement uIElement;
            while ((uIElement = (itemContainerGenerator.GenerateNext() as UIElement)) != null)
            {
                this._uiElementCollection.AddInternal(uIElement);
                itemContainerGenerator.PrepareItemContainer(uIElement);
            }
        }
    }
}

ご覧のとおり、Children プロパティをサポートするフィールドである this._uiElementCollection に常に追加されます。

于 2012-07-26T16:06:28.013 に答える
1

ItemsPanelTemplate は、アイテムをレイアウトするターゲットとして Panel.Children のみを取ることができると思います。実際、たとえば ContentControl から CustomPanel を派生させると、metro スタイル アプリで次の例外メッセージが表示されます。

Exception: The ItemsControl.ItemsPanelTemplate must have a derivative of Panel as the root element.

リンクしたドキュメントは、プログラムでビジュアル ツリーにビジュアルを挿入できる WPF 時からコピーされたドキュメント バグである可能性があります。Metro アプリでは、Panel.Children を使用せずに UIElements の独自のリストをビジュアル ツリーに配置する方法がなくなりました。

于 2012-07-21T07:15:42.537 に答える
0

ItemsPanelTemplate は ItemsControl によって Panel を作成および使用するために使用され、何もしない XAML ではないためです。ItemsControl は、ContentProperty の設定に関係なく、Panel.Children.Add を呼び出すだけです。

Panel は、子をレイアウトするだけで、スタイルを設定することはありません。そのため、Arrange メソッドと Measure メソッドをオーバーライドするだけで済みます。すべてのパネルはそれを行うだけです。

スタイリングやその他のロジックについては、別のアプローチを使用する必要があります。

于 2012-07-19T19:13:23.360 に答える