【问题标题】:How do I implement a WPF control with its own DataTemplate DependencyProperty?如何使用自己的 DataTemplate DependencyProperty 实现 WPF 控件?
【发布时间】:2014-04-21 22:22:08
【问题描述】:

我是一名中级 WPF 开发人员,具有如何实现依赖项属性以及简单的自定义控件的工作知识。我还不明白如何将 DataTemplate 依赖属性添加到自定义控件,并使用它为数据集合中的每个数据定义元素树。

完整的故事是,我一直致力于创建一个 WPF 地图控件,该控件在地图上显示许多不同的点和几何形状,在地图图块上。当用户“拖动”地图时,这些形状将与地图的其余部分一起平移。

我已经完成了这一点,我已经创建了地图控件,并且可以在 Xaml 中向它添加具有地图坐标的子元素。我想更进一步,并为数据集合添加属性,即点、区域等。为了更好地理解我在寻找什么,我想从 ListBox 重新创建两个属性:ItemsSource 和 ItemTemplate。

我已将两个依赖属性添加到我的地图控件 - PointsSource 和 PointsTemplate。 PointsSource 是 IEnumberable 类型,表示要在地图上显示的数据集合。 PointsTemplate 代表这些数据中的每一个应该是什么样子。简单地将这些属性投入到我的控制中显然是不够的,但我不确定如何将它们相互协调。如果有人知道使用自己的 DataTemplate 属性创建自定义数据控件以更改每个数据元素的 UI 树,我将不胜感激。

【问题讨论】:

  • 你基本上是在重新发明ItemsControl。没有必要这样做。从ItemsControl 获得您的控制权,或者简单地使用带有自定义模板和DataTemplates 的香草ItemsControl。无需重新发明轮子 =)
  • 您可能想看看XAML Map Control 中的MapItemsControl 类。它只是从 ListBox 派生的。这样,它不仅继承了 ItemsControl 的 ItemsSourceItemTemplate 等属性,而且还能够在地图上选择项目。
  • @HighCore,我无法从 ItemsControl 继承,原因如下: 我需要的不是一个,而是多个项目源属性——每个都有自己的数据模板;我的控件作为画布很有用,因为我可以使用很多绘图功能;我的代码部分是从另一个开发人员那里继承而来的,而且要尝试重新发明作为 ItemsControl 存在的东西太困难了。如果我以后在自定义控件中遇到与 DataTemplates 相关的问题,我会记住您的建议,但就目前而言:我找到了我喜欢的解决方案。
  • @Clemens,感谢您与我分享该项目,但我已经构建了自己的 MapControl。我有一些额外的业务问题需要通过一些特殊的方式来解决,我发现自己简单地创建一个映射控件会更容易。
  • @MichaelAlexander 见McGarnagle's Answer

标签: c# .net wpf xaml


【解决方案1】:

我在 DataTemplate 本身中找到了我要查找的内容。 DataTemplate 为后面的代码提供了一个名为 LoadContent() 的函数。 LoadContent 生成一个依赖对象,该对象代表给定数据的内容树。根据我在其他地方发现的情况,LoadContent 的常见用法可能如下所示:

foreach (object point in PointsSource)
        {
            FrameworkElement pointElement = _PointsTemplate.LoadContent() as FrameworkElement;
            pointElement.DataContext = point;
            this.Children.Add(pointElement);
        }

上面的代码将为每一个数据元素添加一个内容树,我们给它一个数据来绑定它的DataContext。

【讨论】:

    【解决方案2】:

    如果有人知道如何使用自己的 DataTemplate 属性创建自定义数据控件以更改每个数据元素的 UI 树,我将不胜感激。

    基本上,您需要在控件模板中使用ItemsControl,并将其ItemsSourceItemTemplate 属性绑定到您的自定义依赖属性。即,

    <Style TargetType="{x:Type local:CustomControl}">
        <Setter Property="Template">
            <ControlTemplate TargetType="{x:Type local:CustomControl}">
                <ItemsControl ItemsSource="{TemplateBinding PointsSource}"
                              ItemTemplate="{TemplateBinding PointsTemplate}"
                />
            </ControlTemplate>
        </Setter>
    </Style>
    

    (假设 DPs IEnumerable - "PointsSource" 和 DataTemplate - "PointsTemplate")

    【讨论】:

    • 感谢@McGarnagle,但我找到了一个更合我意的解决方案。我会尽快发布。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-24
    • 2012-01-24
    • 2011-08-06
    相关资源
    最近更新 更多