WPF:DependencyProperty.UnsetValue 在 IMultiValueConverter 中,即使我设置了 DataContext
WPF: DependencyProperty.UnsetValue in IMultiValueConverter even though I set the DataContext
我已经查看了与 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 文件中想要 "iterate through" 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>
最后,烦人的错误 =)
更新
根据@mm8 的评论更新后,我现在看到了这个:
因此,"TheTimeLine" 中的值失败了...
关于 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>
您只能绑定到 public 属性:
public TimeLine TheTimeLine { get; set; }
此外,假设您已将 ItemsSource
属性 绑定到 IEnumerable<GPSLocation>
。如果你想绑定到父 UserControl
class 的 TheTimeLine
属性,你可以使用 RelativeSource
:
<Binding Path="TheTimeLine.TimeStart" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
我已经查看了与 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 文件中想要 "iterate through" 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>
最后,烦人的错误 =)
更新 根据@mm8 的评论更新后,我现在看到了这个:
因此,"TheTimeLine" 中的值失败了...
关于 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>
您只能绑定到 public 属性:
public TimeLine TheTimeLine { get; set; }
此外,假设您已将 ItemsSource
属性 绑定到 IEnumerable<GPSLocation>
。如果你想绑定到父 UserControl
class 的 TheTimeLine
属性,你可以使用 RelativeSource
:
<Binding Path="TheTimeLine.TimeStart" RelativeSource="{RelativeSource AncestorType=UserControl}"/>