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

发布于 2024-12-05 13:01:34 字数 1258 浏览 0 评论 0原文

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

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

--更新--
这是我正在使用的代码,除非用户在其内容周围放置网格,否则它不能用作多个子项的根布局。如果我从 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>

How can I create a control in silverlight that can be used as the layout root, but still have a "Template" property so I can wrap the users content inside another control using a style?

My current implementation is close, it takes the content that the user places in the control and wraps it but the user has to put a grid or panel in if there is multiple controls for the content.

--Update --
This is the code I'm using that will not work as the rootlayout for multiple children unless the user puts a grid around their content. If I inherit from Grid or Panel I get an error about the DefaultStyleKey property not being available.

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>

This is how I want the user to be able to use my new control with out having to wrap their content in a panel or grid.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

貪欢 2024-12-12 13:01:34

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

Seems to me that what you want is to derive your control from an ItemsControl not a ContentControl. In any ControlTemplate that you use you can place the controls using an ItemsPresenter instead of the ContentPresenter you would have used in a ContentControl.

迷迭香的记忆 2024-12-12 13:01:34

如果您希望您的控件能够拥有多个子级,则可以让您的控件继承自Panel。如果这样做,您将必须处理面板子控件的布局。请参阅这篇有关创建自定义面板的 MSDN 文章

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

You can have your control inherit from Panel if you want it to be able to have multiple children. You will have to handle laying out the panel's child controls if you do this. See this MSDN article on creating custom panels.

You can then specify your Template and stick the user content into the template.

亣腦蒛氧 2024-12-12 13:01:34

我认为如果您想要多个控件(即子控件)作为内容,那么您必须使用某种面板,它是 .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 );
    }

I think that if you want multiple controls, i.e. children, as content then you have to use some sort of panel, which is the base class for the .Children property.

Not sure if this is applicable to your situation. I had trouble grasping exactly what's going on in your question. Maybe you can make a custom user control that inherits from ContentControl. As you may or may not know, custom user controls need a default style key. With a custom user control you need to define a template in the default style. Now the template can have a ContentControl somewhere inside of it and its content property should be template binding to the contentcontrol.content property. Or you can override the OnContentChanged function and do whatever you want in that override function (like put a single object in the control by itself... or for multiple objects create a new grid/panel and then set the objects as the grid/panels children for the user and then do what ever it is you are doing with the grid/panel. You would have to set/bind the content property on your new control. Make sense?

I don't know about your error with the default style key, and i don't have any telerik controls, but couldn't you just inherit from your telerik busy indicator? Would something like this work for you, (or put you on the right track).

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 );
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文