Silverlight:TemplateBinding一个Rectangle

时间:2009-12-09 21:33:51

标签: silverlight custom-controls

我有一段时间试图模板绑定矩形的StrokeThickness。

我的目标是允许我的自定义控件的用户设置名为SelectedBorderThickness的属性,实际上,它将设置矩形的StrokeThickness。

我以为我理解模板,但我想我真的没有。

如果我这样做:

<Rectangle x:Name="myRect" Height="100" Width="100" Stroke="Black" SelectedBorderThickness="5" />

有人可以告诉我如何编写Style元素以使其工作吗?

4 个答案:

答案 0 :(得分:1)

您应该为问题添加更多详细信息,人们将能够更轻松地为您提供帮助。我想我已经想出了你想要的东西。

您正在寻找一个自定义模板化的silverlight控件,其中包含一组元素,包括模板中的矩形。您希望用户能够使用控件本身的属性在控件内设置该矩形的厚度。从你上面提到的内容来看,我不知道你在代码中写了多少 - 所以我只会发布一个几乎完整的例子来说明你的目标。

首先,我在visual studio中创建了一个模板化自定义控件,并添加了我们希望用户能够设置的新依赖属性:

public class TestControl : Control
{
    static public DependencyProperty SBTProperty { get; set; }
    static TestControl()
    {
        SBTProperty = DependencyProperty.Register("SelectedBorderThickness", typeof(double), typeof(TestControl),null);
    }

    public TestControl()
    {
        this.DefaultStyleKey = typeof(TestControl);
    }

    public double SelectedBorderThickness
    {
        get { return (double)GetValue(SBTProperty); }
        set { SetValue(SBTProperty, value); }
    }
}

然后我在Generic.xaml中设置了模板(对于我的例子,我控制的唯一东西是矩形,因为我不知道你想要什么):

<Style TargetType="local:TestControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:TestControl">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <Rectangle Fill="Bisque" Stroke="Black" StrokeThickness="{TemplateBinding SelectedBorderThickness}"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

现在我已经准备好在我的应用程序的其他部分使用xaml了。在我的例子中,我把一个放在我的MainPage的中心:

<local:TestControl SelectedBorderThickness="75"></local:TestControl>

编辑: 在阅读下面的代码后,我现在看到问题所在。您正在尝试进行模板绑定,但是您拥有它的方式将尝试绑定到当前模板,该模板是listboxitem的模板,而不是您的自定义列表框。在这种情况下你真正想要的是用FindAncestor做一个RelativeBinding来将树跳到自定义列表框的模板,但是MS还没有在Silverlight中实现那种绑定(即使它在WPF中很常见)。幸运的是,在您的特定情况下,我们可以通过TemplatedParent绑定中的路径来捕获正确的对象,而无需编写一堆杂乱的代码隐藏来模拟祖先绑定:

StrokeThickness="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Parent.SelectedBorderThickness}"

将其转移到上面发布的模板的Rectangle中,它应该可以工作 - 它将访问ListBoxItem的内容(这是你正在显示的内容),然后访问那些对象Parent(这将是你的自定义列表框) 。从那里我们只是打了我们之前设置的房产。

如果您想要更清晰的解决方案,请加入我们的合唱团,要求MS在Silverlight中实现祖先绑定。

答案 1 :(得分:1)

                                                                                                                                                                                                                                                                                                                                                             

答案 2 :(得分:0)

这是问题部分,当我尝试为从ListBox派生的自定义控件设置ItemContainerStyle样式时:

<Setter Property="ItemContainerStyle">
    <Setter.Value>
        <Style TargetType="ListBoxItem">
            <Setter Property="Template">
                <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <Grid Background="{TemplateBinding Background}">
                    <!-- VSM stuff removed for clarity -->
                    <ContentPresenter
                         x:Name="contentPresenter"
                         Content="{TemplateBinding Content}"
                         ContentTemplate="{TemplateBinding ContentTemplate}"
                         HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                         Margin="{TemplateBinding Padding}"/>
                     <Rectangle x:Name="FocusVisualElement" 
                         Stroke="Goldenrod" 
                     StrokeThickness="{TemplateBinding SelectedBorderThickness}" 
                     Visibility="Collapsed" 
                     RadiusX="1" 
                     RadiusY="1" />
                    </Grid>
                </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Setter.Value>
</Setter>

问题是当我在Rectangle上设置StrokeThickness = {TemplateBinding SelectedBorderThickness}然后尝试在测试应用程序中使用该控件时,我得到一个ParserError:

Message: Unknown attribute StrokeThickness on element Rectangle

如果我将StrokeThickness硬编码为3(或其他),它解析得很好,我可以查看测试应用程序。

最后,我真正想做的就是创建一个显示在Intellisense中的属性,以便我的自定义控件的最终用户可以更改颜色和边框的厚度,半径等。突出显示在动态绑定的自定义ListBox中的悬停和选定的ListBoxItem。这不应该是这种困难。

答案 3 :(得分:0)

这些评论太受限制了。我不是想回答我自己的问题(我希望我能)。

David,你的代码在静态添加ListBoxItems时工作正常。动态添加它们时,厚度不会改变。为了测试这个,我在MainPage中添加了一个新的TestControl:

<StackPanel>
  <local:TestControl SelectedBorderThickness="9" x:Name="h1n1">
    <TextBlock Text="Honk1"></TextBlock>
    <TextBlock Text="Honk2"/>
  </local:TestControl>
  <local:TestControl x:Name="SwineFlu" SelectedBorderThickness="20" />
</StackPanel>

在代码隐藏中我添加了:

ObservableCollection<string> test = new ObservableCollection<string>();
test.Add("Hi David");
test.Add("Hello World");
SwineFlu.ItemsSource = test;