WPF Binding can't find data item

倾然丶 夕夏残阳落幕 提交于 2021-01-29 19:17:58

问题


I am quite new to the concept of data binding and MVVM, so I've been trying it out the past couple of days. Basically, what I'm trying to do is using the LiveCharts library, I want to display multiple charts at the same time from an uploaded CSV file.

I am doing well so far, but now I am writing code so that if I want to increase the units in the X-Axis in one chart, I can do so simultaneously with the others. (For context, the x-axis is in the timestamp unit, and the different charts should have the same timestamp, but different IDs and different values under the same timestamp)

The code in my UI is like this (omitted some of the code I think is unnecessary):

<ItemsControl ItemsSource="{Binding SeriesViews}" VerticalAlignment="Top">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Border Background="White">
                     <lvc:CartesianChart Series="{Binding}" Pan="X">
                        <lvc:CartesianChart.AxisX>
                            <lvc:Axis RangeChanged="Axis_RangeChanged" 
                                      MinValue="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=DataContext.Xmin}" 
                                      MaxValue="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=DataContext.Xmax}"
                                      Separator="{x:Static lvc:DefaultAxes.CleanSeparator}">
                            </lvc:Axis>
                        </lvc:CartesianChart.AxisX>
                    </lvc:CartesianChart>
                </Border>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

The other end is like this:

    public GraphData gd;
    public Graphs()
    {
        InitializeComponent();
    }

    public void GenerateCSVList(string csvPath)
    {
        using (var reader = new StreamReader(csvPath))
        using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
        {
            ExcelRecords = csv.GetRecords<Emotions>().ToList();
        }

        gd = new GraphData();
        gd.Xmin = 0;
        gd.Xmax = 5;
        gd.SeriesViews = ReturnChart();
        this.DataContext = gd;
    }

    public ObservableCollection<SeriesCollection> ReturnChart()
        {
            ObservableCollection<SeriesCollection> ChartCollection = new ObservableCollection<SeriesCollection>();
            //Draw charts here
            return ChartCollection
        }

    public class GraphData : INotifyPropertyChanged
        {
            public ObservableCollection<SeriesCollection> SeriesViews { get; set; }
            private double _xmin;
            private double _xmax;

            public event PropertyChangedEventHandler PropertyChanged;
            protected virtual void OnPropertyChanged(string propertyName = null)
            {
                if (PropertyChanged != null)
                    PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
            public double Xmin
            {
                get { return _xmin; }
                set
                {
                    _xmin = value;
                    OnPropertyChanged("Xmin");
                }
            }
            public double Xmax
            {
                get { return _xmax; }
                set
                {
                    _xmax = value;
                    OnPropertyChanged("Xmax");
                }
            }
        }

I'm currently getting this error though for both the min and max values:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.Grid', AncestorLevel='1''. BindingExpression:Path=DataContext.Xmax; DataItem=null; target element is 'Axis' (Name=''); target property is 'MaxValue' (type 'Double')

I would appreciate a nudge in the right direction, since all of this is quite new to me. Is there something I missed with the binding? I thought by putting them in one class I would be able to access them from the UI. Why am I able to view the SeriesViews, but not the Xmin and Xmax from the same class?


回答1:


The issue is definitely, that you don't have a Grid as parent container for your ItemsControl. Change the AncestorType to the ItemsControl and you will gert the binding working.

<lvc:Axis RangeChanged="Axis_RangeChanged" 
          MinValue="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path=DataContext.Xmin}" 
          MaxValue="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path=DataContext.Xmax}"
          Separator="{x:Static lvc:DefaultAxes.CleanSeparator}">
</lvc:Axis>



回答2:


Figured it out. The following is the working code:

<lvc:Axis RangeChanged="Axis_RangeChanged" DisableAnimations="True" Position="LeftBottom" 
      MinValue="{Binding DataContext.Xmin, Source={x:Reference Root}}" 
      MaxValue="{Binding DataContext.Xmax, Source={x:Reference Root}}" 
      Separator="{x:Static lvc:DefaultAxes.CleanSeparator}">

Where I named my UserControl as Root



来源:https://stackoverflow.com/questions/61452281/wpf-binding-cant-find-data-item

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!