Thanks, all - that’s exactly what I was looking for! In case it’s helpful to others, here is my routine as a snippet.
I’m reading a 2-column CSV from the SD card where column 0 is a string label and column 1 is a float value.
//
//	Reading from a CSV stored on the SD card
//	File structure in this example is 2 columns: String,Float
//
File file;
//from https://arduino.stackexchange.com/a/1237
String explode(String data, char separator, int index)
{
	int found = 0;
	int strIndex[] = { 0, -1 };
	int maxIndex = data.length() - 1;
	for (int i = 0; i <= maxIndex && found <= index; i++) {
		if (data.charAt(i) == separator || i == maxIndex) {
			found++;
			strIndex[0] = strIndex[1] + 1;
			strIndex[1] = (i == maxIndex) ? i + 1 : i;
		}
	}
	return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}
void PopulateMenuFromCSV()
{
	file = SD.open("/myFile.csv", FILE_READ);
	if (!file) {
		Serial.println("Error opening file.");
		return;
	}
	//first we need to count the number of lines in the file so we know how large to allocate the colleciton
	int numlines = 0;
	while (file.available())
	{
		file.readStringUntil('\n'); //in this CSV, each line is terminated with a newline character
		numlines++;
	}
	String line;
	file.seek(0); //seek back to the beginning of the file
	//Use the BlynkParamAllocated object to contain the menu labels we want to add
	BlynkParamAllocated items(sizeof(String)*numlines);
	for (int i = 0; i< numlines; i++)
	{
		line = file.readStringUntil('\n');
		
		//split the line at a comma, expecting line format of String,Float
		String name = explode(line, ',', 0); //this will get the item in the first column
		String value = explode(line, ',', 1); //this will get the item in the 2nd column
		float floatval = value.toFloat(); //we expect the second column to contain floats
		if (floatval != 0) //only add a line if we got a valid float (we don't expect 0 as a value in this list)
		{
			items.add(name); //add it to the collection of menu items
		}
	}
	Blynk.setProperty(V30, "labels", items); //push it back to our menu, in this case, Pin 30
	file.close();
}
float GetValueFromMenuSelection(int selectedIndex)
{
	//Blynk menus return 1-based index, so we need to decrement
	selectedIndex = selectedIndex - 1;
	file = SD.open("/myFile.csv", FILE_READ);
	if (!file) {
		Serial.println("Error opening file.");
		return -1;
	}
	for (int i = 0; i < selectedIndex; i++)
	{
		if (file.available())
		{
			file.readStringUntil('\n');
		}
		else
		{
			Serial.println("Error seeking to " + String(selectedIndex));
		}
	}
	//the next line we read should be the selected index line
	String line = file.readStringUntil('\n');
	file.close();
	String name = explode(line, ',', 0);
	String value = explode(line, ',', 1);
	float floatval = value.toFloat();
	if (floatval != 0) { //again, a test to see if we got a valid float and we're not expecting a 0
		Serial.print("Menu item set to " + name + " : ");
		Serial.println(value);
		return floatval;
	}
	else return -1;
}
There’s likely a more efficient way to do this, but hopefully this snippet will help others.
Still, it’d be super awesome to have a menu Widget wrapper that could store both key and value for scenarios like this. The WidgetTable class is so easy to work with in this way - if only I could bind it to a menu 
Anyhow, thanks again. The Blynk platform and community are so awesome.