代码之家  ›  专栏  ›  技术社区  ›  Drew Noakes

wpf-在自定义控件的内容项中使用数据绑定必须满足哪些条件?

  •  3
  • Drew Noakes  · 技术社区  · 15 年前

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

    <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 .

    以下是来自 切片 :

    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 属性对 切片 永远都不可能。如果我将依赖项属性放在 皮埃图 然后复制绑定表达式,然后设置值,所以我确信我了解依赖项属性和绑定的基本知识。

    那么,要让依赖项属性为子项设置值,我需要做什么?由于这些项目都在我自己的集合中,它们是否不知何故不在逻辑树中被任何使绑定起作用的魔法所识别?

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

    编辑 我没说清楚,但车上有环境物体 DataContext 皮埃图 包含属性的 RedCount 等等。在过去,当我在绑定的路径中出现了一个错误(或者其他一些错误)时,我在运行时看到了vs output窗口中的警告。在这种情况下,我什么也看不到。

    2 回复  |  直到 15 年前
        1
  •  3
  •   Drew Noakes    15 年前

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

    小精灵 呼叫 AddLogicalChild 添加 切片 物体。你需要处理 切片 在运行时添加到集合或从集合中移除。这是相当低的级别:msdn建议,“对于控件作者来说,在这个级别操作逻辑树不是推荐的做法,除非可用基本控件类的内容模型都不适合您的控件场景。考虑在 ContentControl , ItemsControl HeaderedItemsControl ."

    制作 小精灵 Panel . 这个 切片 S将是它的孩子,但请注意 Children 属性是弱类型的,因此人们可以向 皮埃图 . 这本质上不是一件坏事或好事,而是一个设计考虑因素(见下面的注释)。但这可能不是你想要的。

    制作 皮埃图 ItemsControl ,和重写 GetContainerForItemOverride , IsItemItsOwnContainerOverride 而且可能 PrepareContainerForItemOverride 创造/尊重 切片 控制.(Cf. ListBox ListBoxItem , ComboBox ComboBoxItem 一个很好的特性是用户可以使用 ItemsSource 和A DataTemplate (像一个 列表框 )而不必手工创建子控件。(但是用户仍然可以创建 切片 根据您的语法使用xaml,就像它们可以创建 ListBoxItems 在XAML中)

    您甚至可以考虑一种混合方法,例如将径向布局功能分解为 RadialLayoutPanel 派片一代变成了 项目控制 其中使用 辐射板 作为其 ItemsPanel .

        2
  •  0
  •   MojoFilter    15 年前

    我认为您看到的问题是绑定试图使用错误的源。我想这样对你有用:

    <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>
    

    我想那很接近,但我可能离得很远。我现在真的查不出来。但听起来不错。(如果完全错了,很抱歉:))