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

use*_*202 8 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()));
Run Code Online (Sandbox Code Playgroud)

这让我在XAML中指定了一堆列.问题是我需要第一列有自定义单元格模板.我打算通过从GridViewColumn派生一个类来解决这个问题,如下所示:

public class TreeGridViewColumn : GridViewColumn
{
}
Run Code Online (Sandbox Code Playgroud)

然后在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>
Run Code Online (Sandbox Code Playgroud)

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

DefaultStyleKeyProperty.OverrideMetadata(typeof(TreeGridViewColumn), new FrameworkPropertyMetadata(typeof(TreeGridViewColumn)));
Run Code Online (Sandbox Code Playgroud)

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

dev*_*hog 1

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

        <TreeGridViewColumn Header="First Col" Width="50">
            <TreeGridViewColumn.CellTemplate>
                <DataTemplate>
                    <Button>
                        click me
                    </Button>
                </DataTemplate>
            </TreeGridViewColumn.CellTemplate>
        </TreeGridViewColumn>
Run Code Online (Sandbox Code Playgroud)

一旦您准备好显示列和单元格,我建议您编写自己的自定义面板,该面板通过调用 FrameworkElements 的 Measure 和 Arrange 方法来处理 FrameworkElements,从而允许您按照您想要的方式定位列和单元格。您最终将在自定义面板类中进行大量数学运算。这还意味着您最终将花费一个月的时间来对 TreeGridView 进行编程。我建议你走捷径,下载这样的东西的代码。网上已经有很少的 TreeListView 了。只需获取他们的 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);
  }
}
Run Code Online (Sandbox Code Playgroud)

DefaultTextCellTemplate 将在 generic.xaml 中设置,如下所示:

<Style TargetType={x:Type DataGridCellControl}>
 <Setter Property="DefaultTextCellTemplate">
  <Setter.Value>
   <DataTemplate>
    <TextBlock Background="Black" Margin="5"/>
     ....
Run Code Online (Sandbox Code Playgroud)

这就是在资源字典中设置默认单元格模板的方法。