代码之家  ›  专栏  ›  技术社区  ›  Ted

WPF:从属财产。在IMultiValueConverter中取消设置值,即使我设置了DataContext

  •  0
  • Ted  · 技术社区  · 7 年前

    我已经研究了与DependencyProperty相关的其他问题。在IMultiValueConverter中取消设置值,但我想我还没有找到与我的问题相关的答案,所以下面是:

    问题是,无论我用DataContext做什么,我都会得到“DependencyProperty.UnsetValue”。

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

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

    http://www.wpf-tutorial.com/data-binding/using-the-datacontext/ )

    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下的绑定标记使用来自timeline(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

    <!-- **** 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 回复  |  直到 7 年前
        1
  •  2
  •   mm8    7 年前

    您只能绑定到 平民的 属性:

    public TimeLine TheTimeLine { get; set; }
    

    DataContext 中的元素 ItemTemplate GPSLocation 对象,假设已绑定 ItemsSource 属性到 IEnumerable<GPSLocation> TheTimeLine 母公司的财产 UserControl 同学们,你们可以使用 RelativeSource :

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