2017-08-14 38 views
0

我環顧了與IMultiValueConverter中的DependencyProperty.UnsetValue相關的其他問題,但我還沒有找到與我的問題有關的答案,我認爲,所以這裏去:WPF:DependencyProperty.UnsetValue在IMultiValueConverter中,即使我設置DataContext

問題是我得到「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。 AS可以蜜蜂看出,ItemsControl的下綁定標籤下面從兩個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

UPDATE 後,我根據@ MM8評論更新,我現在看到這一點:

enter image description here

所以,從 「TheTimeLine」 的值失敗...

的XAML部分有關的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 =這一點;'是WPF MVVM的癌症。 [這篇文章解釋了爲什麼](http://blog.scottlogic.com/2012/02/06/a-simple-pattern-for-creating-re-use-usercontrols-in-wpf-silverlight.html)。你會注意到它有點長,但化療也是如此。 – Will

回答

2

只能綁定到大衆性能:

public TimeLine TheTimeLine { get; set; } 

此外,假設您已將ItemsSource屬性綁定到IEnumerable<GPSLocation>ItemTemplate中元素的DataContextGPSLocation對象。如果你希望綁定到父UserControl類的TheTimeLine屬性,你可以使用一個RelativeSource

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

我也找到了它並刪除了我的評論,抱歉=)AncestorType = UserControl?不是祖先類型的時間線?如果我嘗試使用TimeLine,則會再次出現編譯器錯誤:「Windows Presentation不支持TimeLine」 – Ted

+0

不,源屬性定義的可視祖先類型是UserControl。 – mm8

+0

謝謝,我看看它是否有幫助,但我首先必須解決「使用ItemsSource之前項目集合必須爲空」 - 出現的問題... – Ted