创建可用作布局根目录的Silverlight控件

时间:2011-09-21 18:25:47

标签: silverlight silverlight-4.0

如何在silverlight中创建一个可用作布局根目录的控件,但仍然具有“Template”属性,以便我可以使用样式将用户内容包装到另一个控件中?

我当前的实现很接近,它将用户放置在控件中的内容包装起来,但如果内容有多个控件,则用户必须放入网格或面板。

- 更新 -
这是我正在使用的代码,它不能用作多个子节点的根布局,除非用户在其内容周围放置网格。如果我从Grid或Panel继承,我会收到有关DefaultStyleKey属性不可用的错误。

public class BusyControl :ContentControl
{
    public BusyControl()
    {
        this.DefaultStyleKey = typeof(BusyControl);
    }
}

<Style TargetType="local:BusyControl">
    <Setter Property="Template">
        <Setter.Value>                
            <ControlTemplate TargetType="local:BusyControl">
                <telerik:RadBusyIndicator DisplayAfter="0:0:0.5" IsBusy="{Binding IsBusy}" BusyContent="{Binding BusyMessage}">
                    <ContentPresenter Content="{TemplateBinding Content}" Margin="{TemplateBinding Padding}"/>
                </telerik:RadBusyIndicator>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

这就是我希望用户能够使用我的新控件而不必将其内容包装在面板或网格中的方式。

<cdc:BusyControl x:Name="BusyControl">
        <some:Control x:Name="Control1" />
        <some:Control x:Name="Control2" />
    </cdc:BusyControl>

3 个答案:

答案 0 :(得分:1)

在我看来,您想要的是从ItemsControl而不是ContentControl派生您的控件。在您使用的任何ControlTemplate中,您可以使用ItemsPresenter而不是ContentPresenter中使用的ContentControl来放置控件。

答案 1 :(得分:0)

我认为如果你想要多个控件,即子节点作为内容,那么你必须使用某种面板,这是.Children属性的基类。

不确定这是否适用于您的情况。我无法准确掌握你问题中发生的事情。也许你可以创建一个继承自ContentControl的自定义用户控件。您可能知道或不知道,自定义用户控件需要默认样式键。使用自定义用户控件,您需要以默认样式定义模板。现在,模板可以在其中的某个位置具有ContentControl,并且其content属性应该是与contentcontrol.content属性绑定的模板。或者您可以覆盖OnContentChanged函数并在该覆盖函数中执行任何操作(例如,将单个对象单独放在控件中...或者对于多个对象创建新的网格/面板,然后将对象设置为网格/面板孩子为用户,然后做你正在做的网格/面板。你必须在你的新控件上设置/绑定内容属性。有意义吗?

我不知道您使用默认样式键的错误,并且我没有任何telerik控件,但您不能继承您的telerik忙指示器吗?这样的事情会对你有用吗,(或者让你走上正轨)。

protected override void OnContentChanged( object oldContent, object newContent )
    {
        //I dont know how you are assigning content, 
        //but i would say if it's IEnumerable and count is > 1 it should use your panel
        var newMultiContent = newContent as System.Collections.IEnumerable;
        if ( newMultiContent!=null && newMultiContent.Cast<object>().Count()>1)
        {
            var myNewContentContainer = new StackPanel();//or grid or whatever
            myNewContentContainer.Children.Clear();
            //add children
            foreach (var item in newMultiContent.OfType<UIElement>())
                myNewContentContainer.Children.Add(item);
            //instead of the old content that wasn't what you wanted, use the new content container
            base.OnContentChanged( oldContent, myNewContentContainer );
            //or maybe try this and call the base method at the beginning...
            Content = myNewContentContaint
        }
        else
            base.OnContentChanged( oldContent, newContent );
    }

答案 2 :(得分:0)

如果您希望控件能够拥有多个子级,则可以从Panel继承控件。如果这样做,您将必须处理面板的子控件的布局。见MSDN article on creating custom panels

然后,您可以指定模板并将用户内容粘贴到模板中。