绑定提供有效值。 DependencyProperty 接收 NULL。为什么?

问题描述 投票:0回答:1

我有一个困扰我的绑定。根据值转换器,提供给我的控件的值是有效的且不为空。但最后的

DependencyProperty
总是收到空值。然而,我在输出窗口中没有收到任何绑定警告、错误或任何类型的异常。 (我确实启用了 WPF 日志记录)

我不知道有什么办法可以在

IValueConverter
阶段之后的任何阶段查看我向控件提供的内容。不知道从这里去哪里。

下面是

DependencyProperty
(类本身被缩写为只显示相关属性,因为它很大。我只是想了解这个绑定的问题。 所有其他属性都完美结合)

public class LineControl : Control
{
    static LineControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(
            typeof(LineControl),  ew FrameworkPropertyMetadata(typeof(LineControl)));
    }

    public LineControl() { }

    public static readonly DependencyProperty RegionsProperty = DependencyProperty.Register(
       nameof(Regions), typeof(IEnumerable<ShapeRegion>), typeof(LineControl),
       new FrameworkPropertyMetadata(Enumerable.Empty<ShapeRegion>(), OnRegionsChanged));

   public IEnumerable<ShapeRegion> Regions
   {
       get => (IEnumerable<ShapeRegion>)GetValue(RegionsProperty);
       set => SetValue(RegionsProperty, value);
   }

   private static void OnRegionsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
   {
       // Sanity Check.  I keep getting NULL for the new value here.
    
       if (e.NewValue is not IEnumerable<ShapeRegion>)
           Debug.WriteLine("NULL REGIONS");  // I only get this
       else
           Debug.WriteLine("VALID REGIONS"); // Not this.
   }
}

视图模型

LineShape
是一个相当普通的类,具有绘制线条的属性。精简版

public class LineShape : ObservableObject
{
    private Point _p1;
    private Point _p2;
    private readonly ObservableCollection<ShapeRegion> _regions = new();
    
    public IEnumerable<ShapeRegion> Regions => _regions;
    public Point P1 { get => _p1; set => SetProperty(ref _p1, value);  }
    public Point P2 { get => _p2; set => SetProperty(ref _p2, value);  }
}

这是我绑定的方式

<DataTemplate DataType="{x:Type core:LineShape}">
    <ctrl:LineControl  P1="{Binding P1}"  P2="{Binding P2}"
        Regions="{Binding Regions}" />
</DataTemplate>

正如我所提到的,为了尝试诊断此问题,我尝试在绑定中插入一个不执行任何操作的

IValueConverter
。它记录所提供对象的类型,然后返回给定值不变。像这样

public class LogValueConverter : MarkupExtension, IValueConverter
{
    public override object ProvideValue(IServiceProvider serviceProvider) => this;

    public object Convert(object? v, Type tt, object p, CultureInfo c)
    {
        Debug.WriteLine($"Type = {(v?.GetType() ?? "NULL")}");
        return v;
    }
    public object? ConvertBack(object? v, Type tt, object? p, CultureInfo c) => return v;
}

然后我像这样编辑我的

DataTemplate

Regions="{Binding Regions, Converter={core:LogValueConverter}}"

但每次,此转换器都会记录到输出窗口,表明我正在向绑定提供

ObservableCollection<ShapeRegion>
类型的有效对象。

Type=System.Collections.ObjectModel.ObservableCollection`1[Core.Shapes.ShapeRegion]

然而,我的下一个日志语句(在

LineControl.Regions
的属性更改回调中)每次都会告诉我控件收到了 null。我也用调试器中的断点验证了两者。 我一定错过了一些非常明显的东西,但我不知道它是什么。知道出了什么问题吗?

编辑添加:我无法在简单的示例中重现此问题。这正是我的问题:我过去做过数百次这样的绑定,没有任何问题。但这个尤其表现出我无法理解的行为。我在这里希望有人知道一种方法来更好地诊断单个绑定失败的原因。或者关于可能导致此问题的原因的建议可能会帮助我进一步调查。因为现在我没办法了。

c# wpf
1个回答
0
投票

我终于学会了如何让绑定提供非空值,但

DependencyProperty
仍然接收 null:*当绑定类型为 IEnumerable 并且类型 T 实际上是两种不同的类型时,可能会发生这种情况,因为命名空间冲突。编译器无法捕获它,WPF 也无法发出警告。

在我的例子中,属性的类型是

IEnumerable<ShapeRegion>
问题是两个独立的命名空间中有两个完全独立的类型,名为
ShapeRegion

  • Sdk.ShapeRegion
    ——一个结构体
  • Core.Shapes.ShapeRegion
    ——一堂课

视图模型属性正在提供

IEnumerable<Sdk.ShapeRegion>
,但需要控制
DependencyProperty
IEnumerable<Core.Shapes.ShapeRegion>

通常我会期望这样一个不正确的绑定会导致构建错误。或者至少是一个 WPF XAML 绑定警告。但我两者都没有。当我将自己的

IValueConverter.Convert
函数放入WPF代码中时,我才发现它。

© www.soinside.com 2019 - 2024. All rights reserved.