WPF:IMultiValueConverter中的DependencyProperty.UnsetValue即使我设置了DataContext

时间:2017-08-14 12:29:02

标签: wpf binding itemscontrol

我已经查看了与IMultiValueConverter中的DependencyProperty.UnsetValue相关的其他问题,但我没有找到与我的问题相关的答案,我想,所以这里有:

问题是我得到了" DependencyProperty.UnsetValue"无论我尝试使用DataContext做什么。

我有一个WPF用户控件,在构造函数中我创建了一个对象,如下所示:

 public partial class Misc_Vehicles_GpsTrackBarContext : UserControl
{
    private TimeLine TheTimeLine { get; set; }


    public Misc_Vehicles_GpsTrackBarContext()
    {
        InitializeComponent();

        DateTime start = DateTime.Now.AddDays(-1);
        TheTimeLine = new TimeLine(start, DateTime.Now);
        TheTimeLine.GpsLocations.Add(new GPSLocation(55.13, 13.7, start));
        TheTimeLine.GpsLocations.Add(new GPSLocation(55.14, 13.6, start.AddMinutes(3)));
        TheTimeLine.GpsLocations.Add(new GPSLocation(55.15, 13.5, start.AddHours(6)));
        TheTimeLine.GpsLocations.Add(new GPSLocation(55.16, 13.4, start.AddHours(9)));
        TheTimeLine.GpsLocations.Add(new GPSLocation(55.17, 13.3, start.AddHours(12)));
        TheTimeLine.GpsLocations.Add(new GPSLocation(55.18, 13.2, start.AddHours(15)));

        this.DataContext = this;
    }
}

注意:我现在希望XAML能够访问TheTimeLine(就像这里http://www.wpf-tutorial.com/data-binding/using-the-datacontext/

所以," TheTimeLine"是一个对象,当我在XAML文件中想要"迭代时,我想要使用一些相关数据和对象。 GPS位置:

class TimeLine
{
    public DateTime TimeStart { get; set; }
    public DateTime TimeEnd { get; set; }
    public TimeSpan Duration
    {
        get
        {
            return TimeEnd.Subtract(TimeStart);
        }
    }
    public ObservableCollection<GPSLocation> GpsLocations { get; set; } = new ObservableCollection<GPSLocation>();

    public TimeLine(DateTime start, DateTime end)
    {
        if (start > end)
            throw new ArgumentOutOfRangeException("The start parameter cannot be greater than the end parameter");
        TimeStart = start;
        TimeEnd = end;
    }
}

class DriverSession
{
    public DateTime TimeStart { get; set; }
    public DateTime TimeEnd { get; set; }
    public TimeSpan Duration
    {
        get
        {
            return TimeEnd.Subtract(TimeStart);
        }
    }

    public DriverSession(DateTime start, DateTime end)
    {
        if (start > end)
            throw new ArgumentOutOfRangeException("The start parameter cannot be greater than the end parameter");
        TimeStart = start;
        TimeEnd = end;
    }

}

最后,XAML。可以看出,下面的ItemsControl下的Binding标签使用来自TheTimeLine(TimeStart和TimeEnd)的值,每个GPSPosition都是相同的,然后使用GPSLocation中的ReceivedTime:

<UserControl
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:tWorks.Alfa.OperatorClient.UserControls.Vehicles"
         xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol" x:Class="tWorks.Alfa.OperatorClient.UserControls.Vehicles.Misc_Vehicles_GpsTrackBarContext"
         mc:Ignorable="d" 
         d:DesignHeight="260" Width="764.029">
<UserControl.Resources>
    <LinearGradientBrush x:Key="HourBrush" EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="#FF3EB1EA" Offset="0" />
        <GradientStop Color="#FF61BFF1" Offset="0.5" />
        <GradientStop Color="#FF01A1F4" Offset="1" />
    </LinearGradientBrush>
    <LinearGradientBrush x:Key="MinuteBrush" EndPoint="0.999,0.51" StartPoint="0.045,0.51">
        <GradientStop Color="#FFEDA25E" Offset="0" />
        <GradientStop Color="#FFEDA25E" Offset="0.15" />
        <GradientStop Color="#FFFA7A05" Offset="1" />
    </LinearGradientBrush>
    <local:MarginLengthConverter x:Key="mEventLengthConverter"/>
</UserControl.Resources>

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="2*"></RowDefinition>
        <RowDefinition Height="20"></RowDefinition>
    </Grid.RowDefinitions>

    <Rectangle Fill="AliceBlue"></Rectangle>
    <Grid Grid.Row="1">
        <Rectangle Margin="0" Height="2" Fill="{DynamicResource HourBrush}"/>

        <!-- **** HERE IS THE ItemsControl! **** -->
        <ItemsControl x:Name="GpsLocations" ItemsSource="{Binding Path=TheTimeLine.GpsLocations}">
            <ItemsPanelTemplate>
                <Grid x:Name="EventContainer" Height="20" Background="Gainsboro"/>
            </ItemsPanelTemplate>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Canvas>
    <!-- **** My rectangles (lines) to draw where I have GPS positions **** -->
                        <Rectangle StrokeThickness="0" Width="1" Fill="{DynamicResource MinuteBrush}">
                            <Rectangle.Margin>
                                <MultiBinding Converter="{StaticResource mEventLengthConverter}">
                                    <Binding Path="TheTimeLine.TimeStart"/> <!-- when DataContext is set to "this", i expected TheTimeLine to be accessible? -->
                                    <Binding Path="TheTimeLine.TimeEnd"/> 
                                    <Binding Path="ReceivedTime"/> <!-- ReceivedTime is inside an object called GPSLocation, that I am iterating through -->
                                    <Binding ElementName="EventContainer" Path="ActualWidth"/>
                                </MultiBinding>
                            </Rectangle.Margin>
                        </Rectangle>
                    </Canvas>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
</Grid>

最后,烦人的错误=)

enter image description here

更新 根据@ mm8评论更新后,我现在看到了:

enter image description here

所以,来自&#34; TheTimeLine&#34;的值失败...

关于ItemsControl的XAML部分:

<!-- **** HERE IS THE ItemsControl! TheTimeLine.GpsLocations contains GPSLocation objects that has the ReceivedTime used below **** -->
        <ItemsControl x:Name="GpsLocations" ItemsSource="{Binding Path=TheTimeLine.GpsLocations}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Grid x:Name="EventContainer" Height="20" Background="Gainsboro"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Canvas>
                        <!-- **** My rectangles (lines) to draw where I have GPS positions **** -->
                        <Rectangle StrokeThickness="0" Width="1" Fill="{DynamicResource MinuteBrush}">
                            <Rectangle.Margin>
                                <MultiBinding Converter="{StaticResource mEventLengthConverter}">
                                    <Binding Path="TimeStart" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
                                    <Binding Path="TimeEnd" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
                                    <Binding Path="ReceivedTime"/> <!-- ReceivedTime is inside an object called GPSLocation, ObservableCollection<GPSLocation> -->
                                    <Binding ElementName="EventContainer" Path="ActualWidth"/>
                                </MultiBinding>
                            </Rectangle.Margin>
                        </Rectangle>
                    </Canvas>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

1 个答案:

答案 0 :(得分:2)

您只能绑定到 public 属性:

public TimeLine TheTimeLine { get; set; }

此外,假设您已将DataContext属性绑定到ItemTemplateGPSLocation中元素的ItemsSourceIEnumerable<GPSLocation>对象。如果要绑定到父TheTimeLine类的UserControl属性,可以使用RelativeSource

<Binding Path="TheTimeLine.TimeStart" RelativeSource="{RelativeSource AncestorType=UserControl}"/>