Что должно параметр преобразователя быть для этой привязки

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)
11
задан abatishchev 20 April 2012 в 09:18
поделиться

2 ответа

Параметры для констант, необходимых Вашему преобразователю. Для обеспечения экземпляра объекта преобразователю можно использовать 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>
8
ответ дан 3 December 2019 в 05:36
поделиться

Я назвал бы управление и затем связал бы использование 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} }}"
                      />
1
ответ дан 3 December 2019 в 05:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: