2017-08-14 1 views
0

J'ai regardé autour des autres questions qui se rapportent à DependencyProperty.UnsetValue dans IMultiValueConverter, mais je n'ai pas trouvé de réponse à mon problème, je pense, donc voici le résultat:WPF: DependencyProperty.UnsetValue dans IMultiValueConverter même si j'ai défini le DataContext

Le problème est que j'obtiens "DependencyProperty.UnsetValue" tout ce que j'essaie de faire avec le DataContext.

J'ai un usercontrol WPF, et dans le constructeur je crée un objet, comme celui-ci:

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; 
    } 
} 

Note: J'attends maintenant le XAML pour pouvoir accéder à la TheTimeLine (comme ici http://www.wpf-tutorial.com/data-binding/using-the-datacontext/)

Ainsi, le « TheTimeLine » est un objet qui a des données pertinentes et l'objet que je veux utiliser quand je dans le fichier XAML veux « itérer » les positions 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; 
    } 

} 

Et, enfin, le XAML. AS peut être vu, les tags de liaison sous ItemsControl ci-dessous des valeurs d'utilisation à la fois TheTimeLine (timestart et TimeEnd) qui est la même pour chaque GPSPosition, et utilise ensuite le ReceivedTime qui est en GPSLocation:

<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> 

et enfin, l'erreur gênant =)

enter image description here

MISE à JOUR Après avoir mis à jour selon @ MM8 commentaires, je maintenant voir ceci:

enter image description here

Ainsi, les valeurs de la "TheTimeLine" échoue ...

La partie XAML en ce qui concerne la ItemsControl:

<!-- **** 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> 
+0

'this.DataContext = ceci:' est le cancer de WPF MVVM. [Cet article explique pourquoi] (http://blog.scottlogic.com/2012/02/06/a-simple-pattern-for-creating-re-useable-usercontrols-in-wpf-silverlight.html). Vous remarquerez que c'est un peu long, mais la chimiothérapie aussi. – Will

Répondre

2

Vous ne pouvez lier à public propriétés:

public TimeLine TheTimeLine { get; set; } 

Par ailleurs, le DataContext d'un élément dans le ItemTemplate est un objet GPSLocation en supposant que vous avez lié la propriété ItemsSource à un IEnumerable<GPSLocation>. Si vous voulez lier à la propriété TheTimeLine de la classe parent UserControl, vous pouvez utiliser un RelativeSource:

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

Je l'ai trouvé aussi et j'ai supprimé mon commentaire, désolé =) AncestorType = UserControl? Le AncestorType n'est-il pas une TimeLine? Si j'essaye TimeLine j'obtiens à nouveau l'erreur de compilateur: "TimeLine n'est pas soutenu dans une présentation de Windows" – Ted

+0

Non, le type d'ancêtre visuel où la propriété de source est définie est un UserControl. – mm8

+0

Merci, Ill voir si cela aide, mais je dois d'abord résoudre la "collection d'éléments doit être vide avant d'utiliser ItemsSource" -problème qui est apparu ... – Ted