绑定到DataGrid行工具提示WPF中的嵌套属性

时间:2016-11-05 10:42:21

标签: c# wpf binding datagrid tooltip

我无法解决这个问题。我有一个视图),其中包含一个DataGrid,其中填充了一个可观察集合(MyDataCollection)的项目。 MyDataCollection的每个项目都有不同的属性(Name,Description,...,Logs)。 Logs是Log项目的可观察集合。每个Log项都有不同的属性(Date,Person,...)。

我的数据网格填充了MyDataCollection项,每行设置一个工具提示。像这样:

<DataGrid ItemsSource="{Binding MyDataCollection}">
            <DataGrid.RowStyle>
                <Style TargetType="DataGridRow">
                    <Setter Property="ToolTip">
                        <Setter.Value>
                            <Border>
                                <Grid Margin="5" MaxWidth="400">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="*" />
                                        ...
                                    </Grid.RowDefinitions>

                                    ...
                                    <DataGrid x:Name="LogsGrid" Grid.Row="6" ItemsSource="{Binding PlacementTarget.DataContext.Logs, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ToolTip}}">
                                        <DataGrid.Columns>
                                            <DataGridTextColumn Header="Date" 
                                                Binding="{Binding Date}" 
                                                />
                                            <DataGridTextColumn Header="Person" 
                                                Binding="{Binding Person.FullName}" 
                                                />

                                        </DataGrid.Columns>
                                    </DataGrid>
                                </Grid>
                            </Border>
                        </Setter.Value>
                    </Setter>
                </Style>
            </DataGrid.RowStyle>
        </DataGrid>

我可以看到工具提示,我可以在工具提示中看到带有标题“日期”和“人物”的数据网格,但网格内容为空。看起来绑定设置不正确。任何人都可以帮我一把吗?感谢

更新1: MyDataColletion包含我的自定义类“Car”的对象。这里定义了Car:

public class Car : INotifyPropertyChanged
{
    public string name;
    public string description;
    public Contact assignedTo;
    public ObservableCollection<Log> logs = new ObservableCollection<Log>();
    public string Name
    {
        get
        {
            return this.name;
        }
        set
        {
            if (this.name != value)
            {
                this.name = value;
                NotifyPropertyChanged("Name");
            }
        }
    }
    public string Description 
    {
        get
        {
            return this.description;
        }
        set
        {
            if (this.description != value)
            {
                this.description = value;
                NotifyPropertyChanged("Description");
            }
        }
    }
    public Contact AssignedTo 
    {
        get
        {
            return this.assignedTo;
        }
        set
        {
            if (this.assignedTo != value)
            {
                this.assignedTo = value;
                NotifyPropertyChanged("AssignedTo");
            }
        }
    }

    public ObservableCollection<Log> Logs
    {
        get
        {
            return this.logs;
        }
        private set //TODO : Check if this is correct
        {
            if (this.logs != value)
            {
                this.logs = value;
                NotifyPropertyChanged("Logs");
            }
        }
    }

    public Car()
    {
        // TODO: Delete this: (only here for testing)
        Contact c = new Contact();
        c.Name = "Test";
        c.LastName = "Test";
        for (int i = 0; i < 4; i++)
            AddLog(DateTime.Now, c, new TimeSpan(2, 0, 0));
    }
    public void AddLog(DateTime date, Contact person, TimeSpan time)
    {
        Log newLog = new Log(date, person, time);
        Logs.Add(newLog);
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void NotifyPropertyChanged(string propName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
}

我的日志类是:

public class Log : INotifyPropertyChanged
{
    DateTime date; 
    Contact person;
    TimeSpan time;
    public DateTime Date
    {
        get
        {
            return this.date;
        }
        set
        {
            if (this.date != value)
            {
                this.date = value;
                NotifyPropertyChanged("Date");
            }
        }
    }
    public Contact Person
    {
        get
        {
            return this.person;
        }
        set
        {
            if (this.person != value)
            {
                this.person = value;
                NotifyPropertyChanged("Person");
            }
        }
    }
    public TimeSpan Time
    {
        get
        {
            return this.time;
        }
        set
        {
            if (this.time != value)
            {
                this.time = value;
                NotifyPropertyChanged("Time");
            }
        }
    }

    public Log(DateTime date, Contact person, TimeSpan time)
    {
        this.date = date;
        this.person = person;
        this.time = time;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void NotifyPropertyChanged(string propName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
}

2 个答案:

答案 0 :(得分:0)

而不是ItemsSource="{Binding Logs, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">,请使用:ItemsSource="{Binding PlacementTarget.DataContext.Logs, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ToolTip}}">

答案 1 :(得分:0)

我可以在代码中找到的唯一不适合我的工作是在Mode=TwoWay的绑定LogsGrid.ItemsSource。这引发了我的异常,因为它告诉Binding您希望LogsGridItemsSource的新值写回Binding来源 - 这种情况下,视图模型的Logs属性。这不仅不是你想要的,而且它实际上是不可能的,因为Logs有一个私人的二传手(而且,DataGrid无论如何也不会这样做)。因此例外。

UpdateSourceTrigger=PropertyChanged是另一个没有任何意义的,虽然这次是无害的:它告诉何时将新的Logs集合写回Car.Logs。但同样,DataGrid无法做到这一点。它不会为该属性创建新值。 TextBox会为源属性分配新的Text值,这是TextBox的用途。但是DataGrid并没有做到这一点。

当我摆脱这两件事时,它对我来说很好:

<DataGrid x:Name="LogsGrid" Grid.Row="6" ItemsSource="{Binding Logs}">
    <!-- etc. -->