3

我正在制作一个自定义控件——特别是一个饼图。我希望标记看起来像这个例子:

<c:PieChart>
    <!-- These dependency properties are never set -->
    <c:Slice Value="{Binding RedCount}" />
    <c:Slice Value="{Binding BlueCount}" />
    <c:Slice Value="{Binding GreenCount}" />
</c:PieChart>

PieChart源自Control

[ContentProperty("Slices")]
public class PieChart : Control
{
    public PieChart()
    {
        Slices = new ObservableCollection<Slice>();
    }

    public ObservableCollection<Slice> Slices { get; private set; }
}

上面的 XAML 导致该Slices属性填充三个Slice.

这是来自的片段Slice

public class Slice : ContentControl
{
    public static DependencyProperty ValueProperty
        = DependencyProperty.Register(
            "Value", typeof(double), typeof(Slice),
            new PropertyMetadata((p,a) => ((Slice)p).OnValueChanged(a)));

    private void OnValueChanged(DependencyPropertyChangedEventArgs e)
    {
        // This code never called!
    }
}

问题是永远不会设置Value属性。Slice如果我将依赖属性放在PieChart并复制绑定表达式,则值已设置,因此我确信我了解依赖属性和绑定的基础知识。

那么,我必须做什么才能让我的依赖属性在子项上设置一个值?由于这些项目在我自己的收藏中,它们是否不在逻辑树中,任何魔法都可以使绑定起作用?

一个简单的“这样做”答案会有所帮助,但我真的很想了解这里出了什么问题,所以我会接受发布的最有见地、解释性的答案。

编辑我没有说清楚,但有一些环境对象DataContext包含PieChart属性RedCount等。过去,当我在绑定路径中出现拼写错误(或其他错误)时,我见过运行时 VS 输出窗口中的警告。在这种情况下,我什么也看不到。

4

2 回答 2

3

看起来Slice控件没有连接到可视化树。它们只是成员变量,而 WPF 并不知道将它们显示为PieChart. 几种可能的方法:

PieChart调用AddLogicalChild添加Slice对象。您将需要处理Slice在运行时将 s 添加到集合中或从集合中删除的可能性。这是相当低的级别:MSDN 建议,“对于控件作者,不推荐在此级别操作逻辑树,除非可用基本控件类的内容模型都不适合您的控件方案。考虑在该级别子类化,ContentControl和. ItemsControl"HeaderedItemsControl

PieChart一个Panel. 然后Slices 将成为它的孩子,但请注意该Children属性是弱类型的,因此人们可以向 a 添加任何内容PieChart。这本质上不是一件坏事或一件好事。这是一个设计考虑(见下面的注释)。但这可能不是您想要的。

制作PieChart,ItemsControl并覆盖GetContainerForItemOverride,IsItemItsOwnContainerOverride并可能PrepareContainerForItemOverride创建/尊重Slice控件。(参见ListBoxand ListBoxItem, ComboBoxandComboBoxItem等)其中一个很好的特性是用户可以使用 an ItemsSourceand a DataTemplate(如 a ListBox),而不必手动创建子控件。(但用户仍然可以Slice根据您的语法在 XAML 中创建固定的 s,就像他们可以ListBoxItems在 XAML 中创建一样。)

您甚至可以考虑一种混合方法,例如将径向布局功能分解为 aRadialLayoutPanel并将饼图生成分解为ItemsControl使用 aRadialLayoutPanel作为其ItemsPanel.

于 2009-04-27T21:12:56.420 回答
0

我认为您看到的问题是绑定试图使用错误的来源。我怀疑这样的事情会为你工作:

<c:PieChart>
    <!-- These dependency properties are never set -->
    <c:Slice Value="{Binding RedCount, RelativeSource={AncestorType c:PieChart}}" />
    <c:Slice Value="{Binding BlueCount, RelativeSource={AncestorType c:PieChart}}" />
    <c:Slice Value="{Binding GreenCount, RelativeSource={AncestorType c:PieChart}}" />
</c:PieChart>

我认为这很接近,但我可能还差得很远。我现在真的查不出来。但这对我来说听起来不错。(对不起,如果它完全错误:))

于 2009-04-27T20:47:50.897 回答