private void updateTimingGroup() { beatLength.UnbindBindings(); var tcp = selectedGroup.Value?.ControlPoints.OfType <TimingControlPoint>().FirstOrDefault(); if (tcp == null) { timingPoint = new TimingControlPoint(); // During movement of a control point's offset, this clause can be hit momentarily, // as moving a control point is implemented by removing it and inserting it at the new time. // We don't want to reset the `selectedGroupStartTime` here as we rely on having the // last value to update the waveform display below. selectedGroupEndTime = beatmap.Value.Track.Length; return; } timingPoint = tcp; beatLength.BindTo(timingPoint.BeatLengthBindable); double?newStartTime = selectedGroup.Value?.Time; double?offsetChange = newStartTime - selectedGroupStartTime; var nextGroup = editorBeatmap.ControlPointInfo.TimingPoints .SkipWhile(g => g != tcp) .Skip(1) .FirstOrDefault(); selectedGroupStartTime = newStartTime ?? 0; selectedGroupEndTime = nextGroup?.Time ?? beatmap.Value.Track.Length; if (newStartTime.HasValue && offsetChange.HasValue) { // The offset of the selected point may have changed. // This handles the case the user has locked the view and expects the display to update with this change. showFromTime(displayedTime + offsetChange.Value, true); } }