diff --git a/src/highdicom/content.py b/src/highdicom/content.py
index 844cdee..ddbed2a 100644
--- a/src/highdicom/content.py
+++ b/src/highdicom/content.py
@@ -1867,7 +1867,7 @@ class VOILUTTransformation(Dataset):
                     )
                 for exp in window_explanation:
                     _check_long_string(exp)
-            self.WindowCenterWidthExplanation = window_explanation
+            self.WindowCenterWidthExplanation = list(window_explanation)
         if voi_lut_function is not None:
             if window_center is None:
                 raise TypeError(
diff --git a/src/highdicom/pr/content.py b/src/highdicom/pr/content.py
index b9d000b..48809dd 100644
--- a/src/highdicom/pr/content.py
+++ b/src/highdicom/pr/content.py
@@ -1397,16 +1397,29 @@ def _get_softcopy_voi_lut_transformations(
             for frame_number, frm_grp in enumerate(perframe_grps, 1):
                 if hasattr(frm_grp, 'FrameVOILUTSequence'):
                     voi_seq = frm_grp.FrameVOILUTSequence[0]
+
                     # Create unique ID for this VOI lookup as a tuple
                     # of the contents
+                    width = voi_seq.WindowWidth
+                    center = voi_seq.WindowCenter
+                    exp = getattr(
+                        voi_seq,
+                        'WindowCenterWidthExplanation',
+                        None
+                    )
+
+                    # MultiValues are not hashable so make into tuples
+                    if isinstance(width, MultiValue):
+                        width = tuple(width)
+                    if isinstance(center, MultiValue):
+                        center = tuple(center)
+                    if isinstance(exp, MultiValue):
+                        exp = tuple(exp)
+
                     by_window[(
-                        voi_seq.WindowWidth,
-                        voi_seq.WindowCenter,
-                        getattr(
-                            voi_seq,
-                            'WindowCenterWidthExplanation',
-                            None
-                        ),
+                        width,
+                        center,
+                        exp,
                         getattr(voi_seq, 'VOILUTFunction', None),
                     )].append(frame_number)
 
@@ -1455,10 +1468,20 @@ def _get_softcopy_voi_lut_transformations(
                 )
 
             if has_width:
+                width = ref_im.WindowWidth
+                center = ref_im.WindowCenter
+                exp = getattr(ref_im, 'WindowCenterWidthExplanation', None)
+                # MultiValues are not hashable so make into tuples
+                if isinstance(width, MultiValue):
+                    width = tuple(width)
+                if isinstance(center, MultiValue):
+                    center = tuple(center)
+                if isinstance(exp, MultiValue):
+                    exp = tuple(exp)
                 by_window[(
-                    ref_im.WindowWidth,
-                    ref_im.WindowCenter,
-                    getattr(ref_im, 'WindowCenterWidthExplanation', None),
+                    width,
+                    center,
+                    exp,
                     getattr(ref_im, 'VOILUTFunction', None),
                 )].append(ref_im)
             elif has_lut:

diff --git a/tests/test_pr.py b/tests/test_pr.py
index 8139f1b..b77007d 100644
--- a/tests/test_pr.py
+++ b/tests/test_pr.py
@@ -1348,6 +1348,73 @@ class TestXSoftcopyPresentationState(unittest.TestCase):
         assert gsps.SoftcopyVOILUTSequence[1].WindowWidth == expected_width
         assert gsps.SoftcopyVOILUTSequence[1].WindowCenter == expected_center
 
+    def test_construction_with_copy_voi_lut_multival(self):
+        new_series = []
+        widths = [40.0, 20.0]
+        centers = [400.0, 600.0]
+        for dcm in self._ct_series:
+            new_dcm = deepcopy(dcm)
+            new_dcm.WindowCenter = centers
+            new_dcm.WindowWidth = widths
+            new_series.append(new_dcm)
+        gsps = GrayscaleSoftcopyPresentationState(
+            referenced_images=new_series,
+            series_instance_uid=self._series_uid,
+            series_number=123,
+            sop_instance_uid=self._sop_uid,
+            instance_number=456,
+            manufacturer='Foo Corp.',
+            manufacturer_model_name='Bar, Mark 2',
+            software_versions='0.0.1',
+            device_serial_number='12345',
+            content_label='DOODLE',
+            graphic_layers=[self._layer],
+            graphic_annotations=[self._ann_ct],
+            concept_name=codes.DCM.PresentationState,
+            institution_name='MGH',
+            institutional_department_name='Radiology',
+            content_creator_name='Doe^John'
+        )
+        assert len(gsps.SoftcopyVOILUTSequence) == 1
+        assert gsps.SoftcopyVOILUTSequence[0].WindowWidth == widths
+        assert gsps.SoftcopyVOILUTSequence[0].WindowCenter == centers
+
+    def test_construction_with_copy_voi_lut_multival_with_expl(self):
+        new_series = []
+        widths = [40.0, 20.0]
+        centers = [400.0, 600.0]
+        exps = ['WINDOW1', 'WINDOW2']
+        for dcm in self._ct_series:
+            new_dcm = deepcopy(dcm)
+            new_dcm.WindowCenter = centers
+            new_dcm.WindowWidth = widths
+            new_dcm.WindowCenterWidthExplanation = exps
+            new_series.append(new_dcm)
+        gsps = GrayscaleSoftcopyPresentationState(
+            referenced_images=new_series,
+            series_instance_uid=self._series_uid,
+            series_number=123,
+            sop_instance_uid=self._sop_uid,
+            instance_number=456,
+            manufacturer='Foo Corp.',
+            manufacturer_model_name='Bar, Mark 2',
+            software_versions='0.0.1',
+            device_serial_number='12345',
+            content_label='DOODLE',
+            graphic_layers=[self._layer],
+            graphic_annotations=[self._ann_ct],
+            concept_name=codes.DCM.PresentationState,
+            institution_name='MGH',
+            institutional_department_name='Radiology',
+            content_creator_name='Doe^John'
+        )
+        assert len(gsps.SoftcopyVOILUTSequence) == 1
+        assert gsps.SoftcopyVOILUTSequence[0].WindowWidth == widths
+        assert gsps.SoftcopyVOILUTSequence[0].WindowCenter == centers
+        assert (
+            gsps.SoftcopyVOILUTSequence[0].WindowCenterWidthExplanation == exps
+        )
+
     def test_construction_with_copy_voi_lut_empty(self):
         file_path = Path(__file__)
         data_dir = file_path.parent.parent.joinpath('data')

Failure to create GSPS when reference DICOM uses "MultiValue" for WindowCenter, WindowWidth
When I go to create a GSPS using hd.pr.GrayscaleSoftcopyPresentationState() I get an error for certain DICOM where WindowWidth and WindowCenter are not floats in the reference DICOM. 

Here's the error I get:
```
~/anaconda3/lib/python3.8/site-packages/highdicom/pr/content.py in _get_softcopy_voi_lut_transformations(referenced_images)
   1456 
   1457             if has_width:
-> 1458                 by_window[(
   1459                     ref_im.WindowWidth,
   1460                     ref_im.WindowCenter,

TypeError: unhashable type: 'MultiValue'
```

 I fixed it using the following code: 

``` Python
        if isinstance(image_dataset.WindowWidth, pydicom.multival.MultiValue):
            image_dataset.WindowWidth = image_dataset.WindowWidth[0]
        if isinstance(image_dataset.WindowCenter, pydicom.multival.MultiValue):
            image_dataset.WindowCenter = image_dataset.WindowCenter[0]
```

This fix worked for two offending DICOM, but there is one more where I'm still getting the error. To get rid of the error there, I created the GSPS with my own windowing settings (using the argument voi_lut_transformations=[SoftcopyVOILUTObject]). 
tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_copy_voi_lut_multival tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_copy_voi_lut_multival_with_expl
tests/test_pr.py::TestSoftcopyVOILUTTransformation::test_construction_basic tests/test_pr.py::TestSoftcopyVOILUTTransformation::test_construction_both tests/test_pr.py::TestSoftcopyVOILUTTransformation::test_construction_explanation tests/test_pr.py::TestSoftcopyVOILUTTransformation::test_construction_explanation_mismatch tests/test_pr.py::TestSoftcopyVOILUTTransformation::test_construction_explanation_mismatch2 tests/test_pr.py::TestSoftcopyVOILUTTransformation::test_construction_lut_function tests/test_pr.py::TestSoftcopyVOILUTTransformation::test_construction_luts tests/test_pr.py::TestSoftcopyVOILUTTransformation::test_construction_multiple tests/test_pr.py::TestSoftcopyVOILUTTransformation::test_construction_multiple_mismatch1 tests/test_pr.py::TestSoftcopyVOILUTTransformation::test_construction_multiple_mismatch2 tests/test_pr.py::TestSoftcopyVOILUTTransformation::test_construction_multiple_mismatch3 tests/test_pr.py::TestSoftcopyVOILUTTransformation::test_construction_neither tests/test_pr.py::TestSoftcopyVOILUTTransformation::test_construction_ref_ims tests/test_pr.py::TestGraphicObject::test_circle tests/test_pr.py::TestGraphicObject::test_circle_wrong_number tests/test_pr.py::TestGraphicObject::test_ellipse tests/test_pr.py::TestGraphicObject::test_ellipse_wrong_number tests/test_pr.py::TestGraphicObject::test_filled tests/test_pr.py::TestGraphicObject::test_filled_invalid tests/test_pr.py::TestGraphicObject::test_group_id tests/test_pr.py::TestGraphicObject::test_interpolated tests/test_pr.py::TestGraphicObject::test_point tests/test_pr.py::TestGraphicObject::test_point_wrong_number tests/test_pr.py::TestGraphicObject::test_polyline tests/test_pr.py::TestGraphicObject::test_polyline_wrong_number tests/test_pr.py::TestGraphicObject::test_tracking_ids tests/test_pr.py::TestGraphicObject::test_tracking_ids_invalid tests/test_pr.py::TestGraphicObject::test_units tests/test_pr.py::TestGraphicObject::test_units_invalid tests/test_pr.py::TestTextObject::test_anchor_point_invalid_values tests/test_pr.py::TestTextObject::test_anchor_point_invalid_values_display tests/test_pr.py::TestTextObject::test_anchor_point_wrong_number tests/test_pr.py::TestTextObject::test_bounding_box tests/test_pr.py::TestTextObject::test_bounding_box_br_invalid_for_tl tests/test_pr.py::TestTextObject::test_bounding_box_invalid_values tests/test_pr.py::TestTextObject::test_bounding_box_invalid_values_display tests/test_pr.py::TestTextObject::test_bounding_box_wrong_number tests/test_pr.py::TestTextObject::test_tracking_uids tests/test_pr.py::TestTextObject::test_tracking_uids_only_one tests/test_pr.py::TestGraphicAnnotation::test_construction_both tests/test_pr.py::TestGraphicAnnotation::test_construction_frame_number tests/test_pr.py::TestGraphicAnnotation::test_construction_frame_number_invalid tests/test_pr.py::TestGraphicAnnotation::test_construction_frame_number_single_frame tests/test_pr.py::TestGraphicAnnotation::test_construction_frame_numbers tests/test_pr.py::TestGraphicAnnotation::test_construction_frame_numbers_invalid tests/test_pr.py::TestGraphicAnnotation::test_construction_full_graphic_layer tests/test_pr.py::TestGraphicAnnotation::test_construction_graphic tests/test_pr.py::TestGraphicAnnotation::test_construction_invalid_use_of_matrix tests/test_pr.py::TestGraphicAnnotation::test_construction_multiframe tests/test_pr.py::TestGraphicAnnotation::test_construction_multiple_multiframe tests/test_pr.py::TestGraphicAnnotation::test_construction_out_of_bounds_matrix tests/test_pr.py::TestGraphicAnnotation::test_construction_out_of_bounds_pixel tests/test_pr.py::TestGraphicAnnotation::test_construction_segment_number tests/test_pr.py::TestGraphicAnnotation::test_construction_segment_number_invalid tests/test_pr.py::TestGraphicAnnotation::test_construction_segment_number_single_segment tests/test_pr.py::TestGraphicAnnotation::test_construction_segment_numbers tests/test_pr.py::TestGraphicAnnotation::test_construction_segment_numbers_invalid tests/test_pr.py::TestGraphicAnnotation::test_construction_text tests/test_pr.py::TestAdvancedBlending::test_construction tests/test_pr.py::TestBlendingDisplay::test_construction_equal tests/test_pr.py::TestBlendingDisplay::test_construction_equal_wrong_blending_display_input_type tests/test_pr.py::TestBlendingDisplay::test_construction_equal_wrong_blending_display_input_value tests/test_pr.py::TestBlendingDisplay::test_construction_forebround tests/test_pr.py::TestBlendingDisplay::test_construction_foreground_wrong_blending_display_input_value tests/test_pr.py::TestBlendingDisplay::test_construction_foreground_wrong_relative_opacity_type tests/test_pr.py::TestXSoftcopyPresentationState::test_construction tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_color tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_color_with_gray_images tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_creator_id tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_gray_with_color_images tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_icc_profile tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_palette_color_lut_transformation tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_copy_modality_lut tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_copy_modality_lut_multiframe tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_copy_voi_lut tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_copy_voi_lut_data tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_copy_voi_lut_different tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_copy_voi_lut_empty tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_copy_voi_lut_multiframe tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_copy_voi_lut_multiframe_perframe tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_duplicate_group tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_duplicate_layers tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_group tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_group_missing tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_images_missing tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_missing_layer tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_modality_lut tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_modality_rescale tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_multiple_voi_luts_with_no_ref_ims tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_presentation_both tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_presentation_lut tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_presentation_lut_shape tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_softcopy_voi_lut_with_duplicate_frames tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_softcopy_voi_lut_with_duplicate_frames_2 tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_softcopy_voi_lut_with_duplicate_segments tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_softcopy_voi_lut_with_duplicate_segments_2 tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_softcopy_voi_lut_with_ref_frames tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_softcopy_voi_lut_with_ref_segments tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_voi_lut tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_voi_lut_missing_references tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_voi_lut_two_vois_for_image tests/test_pr.py::TestXSoftcopyPresentationState::test_construction_with_voi_lut_with_ref_ims