【问题标题】:WPF Binding can't find data itemWPF 绑定找不到数据项
【发布时间】:2020-04-27 05:30:27
【问题描述】:

我对数据绑定和 MVVM 的概念还很陌生,所以过去几天我一直在尝试。基本上,我想要做的是使用 LiveCharts 库,我想从上传的 CSV 文件中同时显示多个图表。

到目前为止我做得很好,但现在我正在编写代码,以便如果我想在一个图表中增加 X 轴的单位,我可以与其他图表同时这样做。 (为了上下文,x轴以时间戳为单位,不同的图表应该有相同的时间戳,但同一时间戳下的ID不同,值也不同)

我的UI中的代码是这样的(省略了一些我认为不必要的代码):

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

另一端是这样的:

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

虽然最小值和最大值都出现了这个错误:

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

我希望能朝着正确的方向轻推,因为所有这些对我来说都是全新的。绑定有什么我错过的吗?我认为通过将它们放在一个类中,我将能够从 UI 访问它们。为什么我可以查看 SeriesViews,但不能查看同一类的 Xmin 和 Xmax?

【问题讨论】:

    标签: wpf data-binding


    【解决方案1】:

    问题肯定是,您没有Grid 作为ItemsControl 的父容器。将AncestorType 更改为ItemsControl,您将获得绑定工作。

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

      想通了。以下是工作代码:

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

      我将我的 UserControl 命名为 Root

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-25
        • 2013-10-05
        • 1970-01-01
        • 2011-05-11
        相关资源
        最近更新 更多