“Binding”类型的依赖属性没有更新

发布于 2024-12-08 12:13:50 字数 1296 浏览 4 评论 0原文

我在创建“Binding”类型的 DependencyProperty 时遇到问题。其他类型工作正常,如果我使用绑定填充它们,它们就会成功解析。

在我的场景中,我想获取原始绑定,以便我可以使用它来绑定到子对象的属性,这与 DataGrid 处理列的方式非常相似 - 即,对于列中指定的每个绑定,它绑定到每个ItemsSource 集合中的项目,而不是绑定 DataContext 本身。

<mg:MultiSelectDataGrid x:Name="Grid" DockPanel.Dock="Left" 
     ItemsSource="{Binding Path=Rows}" DataContext="{Binding}" 
     AutoGenerateColumns="False" UriBinding="{Binding Path=UrlItems}">

在我的“MultiSelectDataGrid”中:

    public static readonly DependencyProperty UriBindingProperty = 
       DependencyProperty.Register("UriBinding", typeof(BindingBase),
           typeof(MultiSelectDataGrid), 
           new PropertyMetadata { PropertyChangedCallback = OnBindingChanged});


    private static void OnBindingChanged(DependencyObject d,
                            DependencyPropertyChangedEventArgs e)
    {
         // This is never enterred
    }


    public BindingBase UriBinding
    {
        get { return (BindingBase)GetValue(UriBindingProperty); }
        set { SetValue(UriBindingProperty, value); }
    }

回调永远不会被调用,并且属性永远不会被设置。我尝试过各种排列,有回调,没有回调。唯一给我带来成功的是,如果我用字符串替换绑定(例如 UriBinding="hello") - 在这种情况下,它将触发回调,并设置属性,但当然会失败,因为它是类型错误。

我做错了什么?我已经看过很多这样的例子,我想这就是 DataGrid 本身必须做的事情。

谢谢

I'm having trouble creating a DependencyProperty of type "Binding". Other types work ok, and they resolve successfully if I populate them using a binding.

In my scenario I want to grab the raw binding, so that I can use it to bind to properties of child objects, in much the same way that DataGrid does columns - ie for each binding specified in a column, it binds to each of the items in the ItemsSource collection, rather than binding the the DataContext itself.

<mg:MultiSelectDataGrid x:Name="Grid" DockPanel.Dock="Left" 
     ItemsSource="{Binding Path=Rows}" DataContext="{Binding}" 
     AutoGenerateColumns="False" UriBinding="{Binding Path=UrlItems}">

And in my "MultiSelectDataGrid":

    public static readonly DependencyProperty UriBindingProperty = 
       DependencyProperty.Register("UriBinding", typeof(BindingBase),
           typeof(MultiSelectDataGrid), 
           new PropertyMetadata { PropertyChangedCallback = OnBindingChanged});


    private static void OnBindingChanged(DependencyObject d,
                            DependencyPropertyChangedEventArgs e)
    {
         // This is never enterred
    }


    public BindingBase UriBinding
    {
        get { return (BindingBase)GetValue(UriBindingProperty); }
        set { SetValue(UriBindingProperty, value); }
    }

The callback never gets called, and the property never gets set. I've tried all kinds of permutations, with callbacks, without. The only thing that gave me any success was if I replaced the binding with a string (eg UriBinding="hello") - in that case it would fire the callback, and set the property, but would, of course, fail because it's the wrong type.

What am I doing wrong? I've seen a whole load of examples of this, and I guess this is what DataGrid must be doing itself.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

流年已逝 2024-12-15 12:13:50

奇怪的是,我知道的唯一具有 Binding 类型属性的地方是 DataGridBoundColumn 类,它派生为 DataGridTextColumnDataGridCheckBoxColumn等等...

有趣的是,该属性不是依赖属性。它是一个普通的 CLR 类型属性。我猜绑定的基础设施是基于不能绑定到绑定类型 DP 的限制。

同一类的其他属性都是很好的 DP,例如 Visibility、Header 等。

DataGridBoundColumn 中,Binding 属性声明如下,并对相同内容进行了非常粗略的解释...

这不是 DP,因为如果它获得值就会评估
绑定。

    /// <summary>
    ///     The binding that will be applied to the generated element.
    /// </summary>
    /// <remarks>
    ///     This isn't a DP because if it were getting the value would evaluate the binding.
    /// </remarks>
    public virtual BindingBase Binding
    {
        get
        {
            if (!_bindingEnsured)
            {
                if (!IsReadOnly)
                {
                    DataGridHelper.EnsureTwoWayIfNotOneWay(_binding);
                }

                _bindingEnsured = true;
            }

            return _binding;
        }

        set
        {
            if (_binding != value)
            {
                BindingBase oldBinding = _binding;
                _binding = value;
                CoerceValue(IsReadOnlyProperty);
                CoerceValue(SortMemberPathProperty);
                _bindingEnsured = false;
                OnBindingChanged(oldBinding, _binding);
            }
        }
    }

Curiously only other place I am aware of that has Binding type property is DataGridBoundColumn class which derives into DataGridTextColumn, DataGridCheckBoxColumn etc...

And interestingly there the property is NOT a dependency property. It is a plain CLR type property. I guess the infrastructre of binding is based upon the limitation that you cannot bind to binding type DP.

Other properties of the same class are very well DPs like Visibility, Header etc.

In DataGridBoundColumn the Binding property is declared as below with a very crude explanation for the same ...

This isn't a DP because if it were getting the value would evaluate
the binding.

    /// <summary>
    ///     The binding that will be applied to the generated element.
    /// </summary>
    /// <remarks>
    ///     This isn't a DP because if it were getting the value would evaluate the binding.
    /// </remarks>
    public virtual BindingBase Binding
    {
        get
        {
            if (!_bindingEnsured)
            {
                if (!IsReadOnly)
                {
                    DataGridHelper.EnsureTwoWayIfNotOneWay(_binding);
                }

                _bindingEnsured = true;
            }

            return _binding;
        }

        set
        {
            if (_binding != value)
            {
                BindingBase oldBinding = _binding;
                _binding = value;
                CoerceValue(IsReadOnlyProperty);
                CoerceValue(SortMemberPathProperty);
                _bindingEnsured = false;
                OnBindingChanged(oldBinding, _binding);
            }
        }
    }
情话墙 2024-12-15 12:13:50

虽然 @WPF-it 解决方案有效,但它不适合附加属性,因为您无法附加 CLR 属性。要解决此问题,您可以照常定义附加属性,并通过调用 BindingOperations.GetBindingBase() 获取绑定对象。

private static void OnMyPropChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    // Can also use GetBinding(), GetBindingExpression()
    // GetBindingExpressionBase() as needed.
    var binding = BindingOperations.GetBindingBase(d, e.Property);
}

While @WPF-it solution works, it's unsuitable for attached properties, since you can't attach CLR properties. To solve this you can define your attached property as usual, and get the binding object by calling BindingOperations.GetBindingBase().

private static void OnMyPropChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    // Can also use GetBinding(), GetBindingExpression()
    // GetBindingExpressionBase() as needed.
    var binding = BindingOperations.GetBindingBase(d, e.Property);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文