TL; DR: тип результата обоих вызовов различен. Вызов .map().flatten
возвращает Iterable[(Int, Int)]
, а вызов .flatMap()
возвращает Map[Int, Int]
. Поскольку карта может не содержать один и тот же ключ дважды, первая запись на ключ заменяется второй записью.
Рассмотрим Map
как Iterable[(Key,Value)]
. При вызове .map
вам нужно будет предоставить ему функцию, которая возвращает кортеж, (Key, Value)
(фактические типы могут отличаться от оригинальных Key
и Value
).
В вашем примере, Value
оказывается List[(Int, Int)]
. Когда вы вызываете .map
и возвращаете Value
оригинала Map
, вы в конечном итоге получаете Iterable[List[(Int, Int)]]
, который в результате обращения к .flatten
превращается в Iterable[(Int, Int)]
, объединяя «внутренние» списки вместе. Если бы вы превратили это в карту (вызвав .toMap
), вы бы увидели тот же результат, что и с flatMap
.
Теперь flatMap
отличается тем, что ожидает тип возвращаемого значения Seq[(Key, Value)]
, а не просто (Key, Value)
. Затем он использует возвращенное значение в качестве записей во вновь построенном Map
.
В вашем случае ваш исходный Value
из List[(Int, Int)]
удовлетворяет ожидаемому типу возврата, превращая ваш исходный Map[(String, List[(Int, Int)]
в Map[(Int, Int)]
. Поскольку карта не может содержать две записи с одинаковыми ключами, второе вхождение ключа заменяет более раннее вхождение.
Чтобы увидеть это поведение, полезно использовать REPL (просто запустите scala
) вместо написания основного класса, чтобы вы могли видеть промежуточные значения и их типы.
scala> val theMap = Map("a" -> List(1 ->11,1->111), "b" -> List(2 -> 22, 2 ->222))
theMap: scala.collection.immutable.Map[String,List[(Int, Int)]] = Map(a -> List((1,11), (1,111)), b -> List((2,22), (2,222)))
scala> val mapped = theMap.map(_._2)
mapped: scala.collection.immutable.Iterable[List[(Int, Int)]] = List(List((1,11), (1,111)), List((2,22), (2,222)))
scala> val flattened = mapped.flatten
flattened: scala.collection.immutable.Iterable[(Int, Int)] = List((1,11), (1,111), (2,22), (2,222))
scala> val flatMapped = theMap.flatMap(_._2)
flatMapped: scala.collection.immutable.Map[Int,Int] = Map(1 -> 111, 2 -> 222)
scala> val flattenedToMap = flattened.toMap
flattenedToMap: scala.collection.immutable.Map[Int,Int] = Map(1 -> 111, 2 -> 222)
Параметры для констант, необходимых Вашему преобразователю. Для обеспечения экземпляра объекта преобразователю можно использовать MultiBinding.
Примечание: Для этого решения работать, также необходимо изменить преобразователь для реализации IMultiValueConverter вместо IValueConverter. К счастью, включенные модификации довольно мало. Желание можно добавить проверку для количества значений, предоставленных преобразователю, 2 в случае.
<TextBox Name="Textbox_baysizes">
<TextBox.Text>
<MultiBinding Converter="{StaticResource BaySizeConverter}">
<Binding RelativeSource="{RelativeSource self}" Path="Parent.Parent.BaySizeItemsSource"/>
<Binding ElementName="Textbox_baysizes"/>
</MultiBinding>
</TextBox.Text>
</TextBox>
Я назвал бы управление и затем связал бы использование ElementName:
<UserControl x:Class="BaySizeControl.BaySizeTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BaySizeControl"
Name="Foobar"
>
<UserControl.Resources>
<local:BayListtoStringConverter x:Key="BaySizeConverter"/>
</UserControl.Resources>
<Grid>
<TextBox Name="Textbox_baysizes"
Text="{Binding RelativeSource={RelativeSource self},
Path=Parent.Parent.BaySizeItemsSource,
Converter={StaticResource BaySizeConverter,
ConverterParameter={Binding ElementName=Foobar} }}"
/>
</Grid>
</UserControl>
Нет, ожидайте, который не будет работать, потому что ConverterParameter не является Свойством Зависимости, и при этом Привязкой не является DependencyObject. Расширение разметки ReleativeSource должно сделать то, что Вы хотите, хотя я не использовал вложенный в другом MarkupExtension - возможно, это не хорошего поведения в этом случае:
<TextBox Name="Textbox_baysizes"
Text="{Binding RelativeSource={RelativeSource self},
Path=Parent.Parent.BaySizeItemsSource,
Converter={StaticResource BaySizeConverter,
ConverterParameter={RelativeSource self} }}"
/>