【问题标题】:How to bind to a private property?如何绑定到私有属性?
【发布时间】:2011-10-05 12:57:43
【问题描述】:

我有一个数据网格,我需要其中的所有内容都具有完全可扩展的大小。我对列标题没有任何问题,它们都可以正确缩放。我的问题是单个细胞,它们似乎不尊重它们的结合。

网格高度的绑定似乎可以很好地设置初始值,但是一旦显示网格,如果它绑定的变量发生变化,它不会改变高度。

我必须继承 DataGridTextColumn 来添加一些自定义功能。我有一个名为 CreateDataGridColumn 的方法,它返回对 ExtendedDataGridTextColumn 的引用。然后将这些列添加到数据网格中。数据绑定本身工作正常,网格显示所有正确的数据。

这是一些代码:

    private ExtendedDataGridTextColumn CreateDataGridColumn(EntityBase dataColumn, FormatConditionGroup formatConditionGroup)
    {
        ExtendedDataGridTextColumn newColumn = new ExtendedDataGridTextColumn(dataColumn);
        DataTemplate dataTemplate = new DataTemplate();
        String textBlockName = "Text" + dataColumn.EntityId;
        String columnTag = dataColumn.GetPropertyValue("Tag");

        // Create the TextBlock that will display the cell contents
        FrameworkElementFactory textBlockFNFactory;
        textBlockFNFactory = new FrameworkElementFactory(typeof(TextBlock));

        _gridTextHeightPercentage = dataColumn.GetPropertyDouble("GridFontSize", Constants.DefaultFontHeightPercent) / 2.8;
        _fontSize = GlobalVariables.DesignerPreviewHeight * (_gridTextHeightPercentage / 100);

        Binding binding = new Binding();
        binding.Source = _fontSize;
        textBlockFNFactory.SetBinding(TextBlock.FontSizeProperty, binding);

        // Do a whole bunch of stuff here

        // Create a border so that the label background does not obscure the grid lines
        FrameworkElementFactory borderFNFactory;
        borderFNFactory = new FrameworkElementFactory(typeof(Border));
        borderFNFactory.AppendChild(textBlockFNFactory);

        // Add type to data template
        dataTemplate.VisualTree = borderFNFactory;

        newColumn.CellTemplate = dataTemplate;

        return newColumn;
    }

然后我在数据网格的 SizeChanged 事件上触发了以下方法:

        _customDataGrid.TitleAreaHeight = new GridLength(GlobalVariables.DesignerPreviewHeight * (_titleHeightPercentage / 100));
        _customDataGrid.SetHeaderFontSize(GlobalVariables.DesignerPreviewHeight * (_headerHeightPercentage / 100));
        _fontSize = GlobalVariables.DesignerPreviewHeight * (_gridTextHeightPercentage / 100); 

前两行做了他们应该做的,改变标题区域的高度,这是我添加到我的数据网格的东西,并改变了标题高度。 _fontSize 变量的更新虽然不会改变数据网格单元格的文本高度。

更新

根据建议,我添加了一个依赖属性。

    public static readonly DependencyProperty GridFontHeightProperty = DependencyProperty.Register("GridFontHeight", typeof(double), typeof(CustomDataGrid));

然后把我的绑定代码改成这个。

        binding = new Binding();
        binding.Path = new PropertyPath("GridFontHeight");
        textBlockFNFactory.SetBinding(TextBlock.FontSizeProperty, binding);

然后在我的尺寸改变了添加这个。

        SetValue(GridFontHeightProperty, _fontSize);

但它不起作用。在这种情况下,它没有正确设置字体高度,它只是使用数据网格的默认字体高度。

【问题讨论】:

  • 我以为我在展示绑定。我创建一个绑定对象,设置源,然后以编程方式调用 SetBinding。

标签: wpf binding


【解决方案1】:

首先,不,您不能绑定到私有变量。我的猜测是,您的变量 _fontSize 是private double,对吧? (看看我怎么猜?;)) 您可以绑定到公共 property 或依赖项属性,这在您的情况下非常适合。所以创建一个名为 FontSize 的新依赖属性并绑定到它。

如果由于某种原因您不能使用依赖属性,您仍然可以使用 INotifyPropertyChanged 绑定到正常的 CLR 属性,看起来应该类似于

public double FontSize
{
    get{return _fontSize;}
    set
    {
        _fontSize = value;
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs("FontSize"));
        }
    }
}

【讨论】:

  • 更新了我的问题以反映我尝试过的方法,使用了一个不起作用的依赖属性。
【解决方案2】:

我对此有几个意见...

  1. 你的ExtendedDataGridTextColumn 是从DataGridTextColumn 扩展而来的吗?如果是,你怎么会使用CellTemplateDataGridTextColumn 具有 ElementStyleEditingElementStyle 以设置其单元格表示的 TextBlock 和 TextBox 的样式。

  2. 如果您对上述第 1 点中关于 CellTemplate 的决定有信心,请尝试....

      Binding binding = new Binding();
      binding.BindsDirectlyToSource = true;
      binding.Source = _fontSize;
      textBlockFNFactory.SetBinding(TextBlock.FontSizeProperty, binding); 
    

如果有任何帮助,请告诉我。

【讨论】:

  • +1 for BindsDirectlyToSource 不确定它是否与 new Binding(".") 相同甚至可能,并且忘记了该属性。
  • 对于你的第一个问题,是的,它确实扩展了它。在我创建 ExtendedDataGridTextColumn 的代码中,我动态地创建了几个触发器。这些是在 XML 文件中配置的,但它们可能是特定列上的 20 个触发器中的多个。我将这些触发器添加到 DataTemplate 对象,然后将其分配给 CellTemplate。如果我能简化一下,那就太好了。
  • 对于第二个答案,它没有任何区别。正如 dowhilefor 所指出的,_fontSide 是在创建 ExtendedDataGridTextColumn 的类中声明的私有 double,而不是在 ExtendedDataGridTextColumn 类本身中声明。
  • 我将 _fontSize 移到了 ExtendedDataGridTextColumn 类,但这也不起作用。最终我想绑定到数据网格级别的属性集,因为在我的实现中,所有单元格都将具有完全相同的文本高度,我只想更新一次变量/属性以更改所有列。跨度>
【解决方案3】:

你没有正确绑定,也不能做(严格来说)你想要的。

绑定总是针对普通代码属性或依赖属性。您不能绑定到字段。你可以这样做:

首先,删除_fontSize 实例变量。你不会再使用它了。

接下来,为这个值定义一个DependencyProperty

    private const string FontSizePropertyName = "FontSize";
    private static readonly DependencyProperty FontSizeProperty = 
    DependencyProperty.Register(
        FontSizePropertyName,
        typeof(double),
        typeof(ExtendedDataGridTextColumn),
        new UIPropertyMetadata(0));
    private double FontSize
    {
        get { return (double)GetValue(FontSizeProperty); }
        set { SetValue(FontSizeProperty, value); }
    }

然后将您的绑定更改为:

    Binding binding = new Binding();
    binding.Source = RelativeSource.Self;
    binding.Path = new PropertyPath(FontSizeProperty)
    textBlockFNFactory.SetBinding(TextBlock.FontSizeProperty, binding);

然后只需使用新的 FontSize 属性来设置值,而不是更新私有字段。

注意:您已接近现有的依赖项属性,但如果该属性是 CLR(普通)属性,PropertyPath 仅采用 string。对于依赖属性,您应该将实际的 DependencyProperty 实例传递给它,如上所示。

【讨论】:

  • 最后一行参数 new UIPropertyMetadata(0) 会导致抛出异常,如果我删除它没有异常但它不起作用。由于某种原因,它也确实减慢了重绘速度。也许我需要向您发送一个包含实际课程的大样本。
  • @WPFNewbie:试试0.0 而不是0
  • 这段代码应该去哪里?目前它在我的自定义数据网格类中,它创建了单独的数据列。我确实尝试将其全部移动到 ExtendedDataGridTextColumn 类,这使得它变得非常慢,比如渲染一个包含 20 条记录的数据网格需要 10 秒,但它仍然不遵守绑定。
  • @WPFNewbie:它应该放在_fontSize 字段之前的任何位置。如果ExtendedDataGridTextColumn 中没有,那么上面代码中的typeof(ExtendedDataGridTextColumn) 应该是typeof(TypeWhereThePropertyIs)
  • 感谢您花时间尝试帮助我。它仍然无法正常工作。它根本没有获得字体高度,它使用的是默认字体高度。顺便说一句,0.0 确实解决了引发异常的另一个问题。
猜你喜欢
  • 2011-11-10
  • 2018-03-25
  • 2018-05-09
  • 2023-01-20
  • 1970-01-01
  • 1970-01-01
  • 2017-05-26
  • 2011-09-14
  • 2018-08-08
相关资源
最近更新 更多