正如 Kent 所说,在 MVVM 方法中,您可以定义具有两个集合的 ViewModel,一个用于用户输入数据,一个用于公开路径可以绑定到的转换后的项目。然后您需要定义何时需要刷新路径的集合。这意味着使用用户输入的坐标手动订阅CollectionChanged集合事件(仅当用户可以添加或删除点时)和PropertyChanged每个用户坐标的事件(在任何情况下)。这是否需要,取决于您是否要允许用户更改列表中已有的坐标。
坐标在添加到列表后不会更改
如果没有,还有一种更直接的方法,即使用 ValueConverter。由于您当时想要实现的是直接转换,我建议使用内置的 WPF 机制进行转换。这些适用于 MVVM 和非 MVVM 方法。
定义一个转换器,将坐标转换为存储在 DataGrid 的每个项目中的坐标ItemsSource到路径段。这包含您已经计算出的数学,仅此而已:
public class CoordinateToPathSegment : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var coordinate = value as CurveViewModel.Coordinate;
        var segment = new QuadraticBezierSegment();
        // Set properties of quadratic bezier element
        return segment;
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
您在应用程序/窗口/控件的资源中公开此转换器的实例。有关转换器的一般信息,请参见此处:WPFTutorial: Converters。
然后将它们连接在一起,如下所示:
 <Path Data="{Binding ItemsSource, 
                      ElementName=CoordinateGrid, 
                      Mode=OneWay, 
                      Converter={StaticResource CoordinateToSegmentConverter}}" />
这样,您的路径始终与数据网格同步,并且用户输入坐标会自动转换为路径段,而无需您自己关心刷新。同样:请注意,已经存在的 UserCoordinate 的更改不会转发到 UI,因为一旦坐标转换为 a PathSegment,两者之间就不再有引用。只有在 DataGrid 中添加/删除坐标时,路径才会刷新。
在将坐标添加到列表后,用户可以更改坐标
如果您想允许用户更改已定义坐标的单个值,还有更多内容。然后你需要得到肯特提议的方式。原理大概是这样的:
public class CurveViewModel : ViewModelBase
{
    private Collection<PathSegment> _segments;
    private readonly ObservableCollection<Coordinate> _userInputCoordinates;
    public ObservableCollection<Coordinate> UserInputCoordinates
    {
        get { return _userInputCoordinates; }
    }
    public Collection<PathSegment> Segments
    {
        get { return _segments; }
        private set
        {
            _segments = value;
            OnPropertyChanged(() => Segments);
        }
    }
    public CurveViewModel()
    {
        _userInputCoordinates = new ObservableCollection<Coordinate>();
        // Subscribe to refresh the path on adding/deleting ne coordinates
        UserInputCoordinates.CollectionChanged += UserInputCoordinates_CollectionChanged;
    }
    private void UserInputCoordinates_CollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
    {
        switch (args.Action)
        {
            case NotifyCollectionChangedAction.Add:
                var newItems = args.NewItems.OfType<INotifyPropertyChanged>();
                foreach (var coordinate in newItems)
                {
                    // Subscribe to property change of a particular coordinate to refresh the 
                    // curve when user changes the values of an already existing coordinate data set
                    coordinate.PropertyChanged += Coordinate_PropertyChanged;
                }
                break;
            case NotifyCollectionChangedAction.Remove:
                var oldItems = args.OldItems.OfType<INotifyPropertyChanged>();
                foreach (var coordinate in oldItems)
                {
                    // Unsubscribe to avoid memory leaks
                    coordinate.PropertyChanged -= Coordinate_PropertyChanged;
                }
                break;
        }
        // This refreshes the path when a coordinate has been added/removed
        RefreshPath();
    }
    private void Coordinate_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        RefreshPath();
    }
    private void RefreshPath()
    {
        var segments = new Collection<PathSegment>();
        foreach (var userInputCoordinate in UserInputCoordinates)
        {
            var segment = new QuadraticBezierSegment();
            // Set properties here
            segments.Add(segment);
        }
        Segments = segments;
    }
    public class Coordinate : ViewModelBase
    {
        private double _xStart;
        public double XStart
        {
            get { return _xStart; }
            set
            {
                _xStart = value;
                OnPropertyChanged("XStart");
            }
        }
        // Analogous properties for YStart, XEnd, YEnd, XControl, YControl
    }
}
然后你将Data路径绑定到Segments. 我希望评论或多或少地解释了它是如何工作的。
让我知道这是否回答了您的问题并解决了问题。