如何将样式应用于自定义控件库中的DependencyObject

时间:2016-01-20 01:21:13

标签: wpf

我正在创建一个基于TreeView的可重用自定义控件。我在自定义控件上为控件中的列创建了依赖项属性,如下所示:

    public GridViewColumnCollection Columns
    {
        get { return (GridViewColumnCollection)GetValue(ColumnsProperty); }
        set { SetValue(ColumnsProperty, value); }
    }

    public static readonly DependencyProperty ColumnsProperty =
        DependencyProperty.Register("Columns", typeof(GridViewColumnCollection), typeof(TreeListView), new PropertyMetadata(new GridViewColumnCollection()));

这允许我在XAML中指定一堆列。问题是我需要第一列有自定义单元格模板。我将通过从GridViewColumn派生一个类来实现这一点,如下所示:

public class TreeGridViewColumn : GridViewColumn
{
}

然后在Generic.xaml中为自定义控件提供所需的样式:

<Style TargetType="{x:Type local:TreeGridViewColumn}">
    <Setter Property="CellTemplate">
        <Setter.Value>
            <DataTemplate>
                <Border Background="Black" /> <!-- Just for example -->
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

但是样式永远不会应用于TreeGridViewColumn的实例。我知道我可能需要添加:

DefaultStyleKeyProperty.OverrideMetadata(typeof(TreeGridViewColumn), new FrameworkPropertyMetadata(typeof(TreeGridViewColumn)));

但是我不能这样做,因为GridColumn基类不是FrameworkObject,它是DependencyObject。如何将样式应用于自定义控件库中定义的GridViewColumn的后代?

1 个答案:

答案 0 :(得分:1)

这样想:TreeGridViewColumn应该是一个虚拟对象,它包含列本身的重要信息,如宽度和高度,以及该列标题下的每个单元格,例如单元格模板本身。因此,不要尝试从TreeGridViewColumn创建FrameworkElement。下面是一个如何最终使用TreeGridViewColumn的示例。

        <TreeGridViewColumn Header="First Col" Width="50">
            <TreeGridViewColumn.CellTemplate>
                <DataTemplate>
                    <Button>
                        click me
                    </Button>
                </DataTemplate>
            </TreeGridViewColumn.CellTemplate>
        </TreeGridViewColumn>

一旦你准备好显示列和单元格,我建议你编写自己的自定义面板,通过调用它们的Measure和Arrange方法处理FrameworkElements,允许你按照你想要的方式定位列和单元格。您最终会在自定义面板类中进行大量数学运算。更进一步意味着你将花费一个月的时间来编程TreeGridView。我建议你走捷径并下载这样的代码。在线已经有很少的TreeListViews。只需拿走他们的dll,看看它是否适合你

编辑:

好的,这里有一个建议如何解决您的问题。这只是一个建议

DefaultTextColumnData类是一个虚拟对象,包含所有必要的信息,如列宽等。

DataGridCellControl将是绘制单元格的FrameworkElement。它是一个FrameworkElement,因此它将在你的generic.xaml资源字典中有一个已定义的样式。

总结一下,DefaultTextColumnData将保存列本身的所有信息。 DataGridCellControl将是一个控件,如果你在该列中有20个单元格,它最终可能会有20个自身实例。

DataGridCellControl必须知道它的列。 这就是DataGridCellControl的代码看起来很相似的方式:

class DefaultTextColumnData : DataGridColumn
{
}

class ComplexColumnData : DataGridColumn
{
}

class DataGridCellControl : Control
{
  public DataGridColumn Column
  {
    get; set;
  }

  public DataTemplate DefaultTextCellTemplate
  {
    get; set;
  }

  public override Size MeasureOverride(Size size)
  {
   ...
   if(this.Column is DefaultTextColumnData)
   {
    this.Template = this.DefaultTextCellTemplate
   }

   if(this.Column is ComplexColumnData)
   {
    this.Template = ...
   }
   ...
   return new Size(30, 30);
  }
}

DefaultTextCellTemplate将在你的generic.xaml中设置如下:

<Style TargetType={x:Type DataGridCellControl}>
 <Setter Property="DefaultTextCellTemplate">
  <Setter.Value>
   <DataTemplate>
    <TextBlock Background="Black" Margin="5"/>
     ....

如何在资源字典中设置默认单元格模板。