多绑定时随机DependencyProperty.UnsetValue

问题描述

我遇到一个奇怪的问题。

我在一个可观察的集合中得到了一个spaceObjects(行星)集合。这些对象在屏幕上移动,因此它们的X和Y轴一直在变化。这是它的xaml代码

<DataTemplate DataType="{x:Type spaceObjects:SpaceObject}">
                    <Path Fill="{Binding Color,Converter={StaticResource ColorConverter}}"
                          stroke="{Binding Border,Converter={StaticResource ColorConverter}}"
                          strokeThickness="{Binding BorderThickness}" Tag="{Binding Name}">
                        <Path.Data>
                            <EllipseGeometry RadiusY="{Binding Radius}" RadiusX="{Binding Radius}">
                                <EllipseGeometry.Center>
                                    <MultiBinding Converter="{StaticResource XYPositionConverter}">
                                        <Binding Path="X"></Binding>
                                        <Binding Path="Y"></Binding>
                                    </MultiBinding>
                                </EllipseGeometry.Center>
                            </EllipseGeometry>
                        </Path.Data>
                    </Path>
                </DataTemplate>

由于大量冗余信息,我将xaml代码缩短了很多。只需知道这是一个具有多种对象的observablecollection(这就是我使用datatemplate的原因),并且存在此datatemplate的itemscontrol也绑定到另一个collection。我认为这与问题无关。

因此,在我们进入错误代码之前,我将向您展示一些不会引发错误代码。 此方法移动spaceObjects并执行与UI不相关的其他一些操作。没问题。

private void MoveAndCheckLegacy(Object source,ElapsedEventArgs e)
        {
            Parallel.For(0,_spaceObjects.Count,i =>
            {
                var isspaceObject = _spaceObjects[i] is SpaceObject;
                if (isspaceObject)
                {
                    var spaceObject = (SpaceObject) _spaceObjects[i];
                    spaceObject.Move();
                    CheckForCollisionLegacy(spaceObject);
                }
                else
                {
                    var lineObject = (LinespaceObject) _spaceObjects[i];
                    lineObject.UpdatePosition();
                }
            });
        }

它只是循环遍历observablecollection中的spaceObject,更改其X和Y。多重绑定会注意到这一点并采取相应的行动。

现在,我编写了一个更大的方法,该方法也将元素插入QuadTree中,但活动部分只是像以前一样(以前也是parralel,但是我在调​​试此问题时对其进行了更改)是for循环的一部分。

var qtree = new QuadTree(new Rectangle(0,800,600),"base");

            for (int i = 0; i < _spaceObjects.Count - 1; i++)
            {
                var isspaceObject = _spaceObjects[i] is SpaceObject;
                if (isspaceObject)
                {
                    var spaceObject = (SpaceObject)_spaceObjects[i];
                    spaceObject.Move();
                    // Printing X and Y and Name for debugging purposes
                    Trace.WriteLine($"{spaceObject.Name}: ({spaceObject.X},{spaceObject.Y})");
                }
                else       // Some stuff to do with other objects. 
                {
                    var lineObject = (LinespaceObject)_spaceObjects[i];
                    lineObject.UpdatePosition();
                }
            }
             // Insert spaceObjects into QuadTree
            for (int i = 0; i < _spaceObjects.Count - 1; i++)
            {
                var so = _spaceObjects[i] is SpaceObject;
                if (so) qtree.Insert((SpaceObject)_spaceObjects[i]);
            }
            
            // Show Quadtree on UI
            ShowQtree(qtree);

这可以运行一会儿,但是随后我的转换器抛出DependencyProperty.UnsetValue错误。 所以我开始打印我的转换器接收的值,然后再执行以下转换:

public object Convert(object[] values,Type targettype,object parameter,CultureInfo culture)
        {
            Trace.WriteLine($"({values[0]}. {values[1]})");
            var i = (decimal) values[0];
            var y = (decimal) values[1];

            var a = (int) i;
            var b = (int) y;

            return new Point(a,b);
        }

现在很奇怪。我还打印了行星的x,y值(出于调试目的)。 如果可观察的集合中仅存在一个spaceObject,则为输出

Kobol: (127,5,12,0)
(127,5. 18,0)
Kobol: (127,8,11,4)
(127,5. 11,4)                 <<<<< right here
({DependencyProperty.UnsetValue}. 11,4)

似乎在尝试转换任何东西之前,转换器具有正确的值! 我将“就在这里”放在可以看到转换器内部值的地方。 然后在下一刻,它似乎又进入了转换器,现在它没有值了。 我敢打赌,实际的行星确实具有X和Y值(但是无法检查,因为在调试时应用程序会冻结:()。这种移动算法没有改变,并且没有任何问题(仍然可以正常工作)。

有人有任何想法或建议吗?

如果不清楚,请告诉我。我将在需要的地方删除添加详细信息。

编辑**

在注释掉涉及移动和四叉树的大多数方法之后,我像最小的复杂移动方法一样使它工作。可能是我的方法太大了吗?我忘了提到它在Timer线程中运行。...也许它太慢了,会导致问题?

解决方法

您的XYPositionConverter必须处理这个特殊值。在探查转换器时,WPF将使用DependencyProperty.UnsetValue。这通常是在创建DataTemplate时发生的,也许是看不见的。

因此,只需确保在转换器中进行处理即可

public class XYPositionConverter : IMultiValueConverter
{
    public object Convert(object[] values,Type targetType,object parameter,CultureInfo culture)
    {
        if (values == null ||
            values.Any(x => x == null || x == DependencyProperty.UnsetValue))
        {
            return DependencyProperty.UnsetValue;
        }
        // ...
        return result;
    }
    // ...
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...