Привязка WPF ListBox ListBoxItem

Я просматриваю книгу Самса «Научите себя WPF за 24 часа». В какой-то момент авторы показывают, как можно привязать значение selected-item ListBox к свойству. Я понимаю, это довольно просто. Но когда я пытаюсь создать свой собственный элемент управления ListBox с моими собственными ListBoxItems, я не могу заставить его работать.

Работающий ListBox использует системную коллекцию в качестве свойства ItemsSource:

<ListBox x:Name="FontList"
         DockPanel.Dock="Left"
         ItemsSource="{x:Static Fonts.SystemFontFamilies}"
         Width="160" />

Значение, выбранное из этого ListBox, затем используется в TextBlock следующим образом:

<TextBlock Text="Test" 
           FontFamily="{Binding ElementName=FontList, Path=SelectedItem}"
           TextWrapping="Wrap"
           Margin="0 0 0 4" />

Обратите внимание, что для параметра Path установлено значение SelectedItem.

Теперь я хотел установить FontSize с помощью другого ListBox, который содержит 3 разных размера. Вот что я сделал:

<ListBox x:Name="Size" >
    <ListBoxItem>10</ListBoxItem>
    <ListBoxItem>15</ListBoxItem>
    <ListBoxItem>20</ListBoxItem>
</ListBox>

Затем я добавил привязку к атрибуту Size TextBox следующим образом:

<TextBlock Text="Test" 
           FontFamily="{Binding ElementName=FontList, Path=SelectedItem}"
           Size="{Binding ElementName=Size, Path=SelectedItem}"
           TextWrapping="Wrap"
           Margin="0 0 0 4" />

Размер не меняется при запуске программы. Поэтому я попытался добавить привязку, которую я использовал для размера, к атрибуту Text - чтобы увидеть его значение:

<TextBlock Text="{Binding ElementName=Size, Path=SelectedItem}"" 
           FontFamily="{Binding ElementName=FontList, Path=SelectedItem}"
           Size="{Binding ElementName=Size, Path=SelectedItem}"
           TextWrapping="Wrap"
           Margin="0 0 0 4" />

Я вижу, что он меняется, когда я нажимаю Size ListBox, но я также вижу, что SelectedItem отображается следующим образом (когда я нажимаю запись 15): System.Windows.Controls.ListBoxItem: 15

Мои вопросы: 1) Какое фактическое значение возвращает путь SelectedItem? Это «System.Windows.Controls.ListBoxItem: 15» или «15»? Если это не 15, как я могу указать путь, который возвращает только 15, а не System.Windows.Controls.ListBoxItem: 15?

2) Почему работает FontFamily SelectItem? Я понимаю, что FontList исходит из коллекции имен шрифтов System, но мне неясно, почему ListBox не возвращает коллекцию ListBoxItems в виде текста. Если моя ссылка на ListBox Path возвращает объект SelectedItem типа ListBoxItem, тогда я бы подумал, что могу использовать Path of SelectedItem.Value или что-то в этом роде, но это не работает, и Intellisense не может мне помочь.

Я хочу, чтобы этот пример работал, потому что он поможет прояснить некоторые мои недоразумения. Пожалуйста, не реорганизуйте решение, чтобы заставить его работать каким-то другим способом, если только для меня совершенно невозможно иметь ссылку на путь, которая даст мне только числовую часть моего выбранного элемента ListBoxItem размера.


person Jazimov    schedule 17.03.2012    source источник


Ответы (2)


Какое фактическое значение возвращает путь SelectedItem?

Это System.Windows.Controls.ListBoxItem:15 (вы можете прочитать это как «ListBoxItem с содержимым, установленным на 15»), поэтому ваша привязка не работает - она ​​ожидает числовое значение, а не ListBoxItem. Вы можете указать Path как SelectedItem.Content, чтобы это сработало. Также вы можете установить SelectedValuePath для ListBox "Size" в "Content" и привязать к свойству SelectedValue вместо SelectedItem.

Решение 1:

<TextBlock Size="{Binding ElementName=Size, Path=SelectedItem.Content}" />

Решение 2:

<ListBox x:Name="Size" SelectedValuePath="Content" />
<TextBlock Size="{Binding ElementName=Size, Path=SelectedValue}" />

Почему работает FontFamily SelectItem?

Поскольку этот ListBox содержит коллекцию шрифтов, а не коллекцию ListBoxItems (хотя они по-прежнему создаются для представления каждого элемента в коллекции). Вы можете добиться того же поведения с размерами шрифта, если вы определите коллекцию размеров шрифта в коде и привяжете свойство ListBox's ItemsSource к этой коллекции или определите содержимое вашего ListBox как коллекцию значений System.Double непосредственно в XAML:

<ListBox x:Name="Size"
         xmlns:system="clr-namespace:System;assembly=mscorlib">
    <system:Double>10</system:Double>
    <system:Double>15</system:Double>
    <system:Double>20</system:Double>
</ListBox>
person max    schedule 17.03.2012

1) Фактическое значение, возвращаемое вашей привязкой SelectedItem, является объектом ListBoxItem. Чтобы получить значение (15) из привязки, вы можете использовать конвертер или сделать свой путь привязки более явным, чтобы получить значение свойства Content элемента списка:

Size="{Binding ElementName=Size, Path=SelectedItem.Content}"

2) Это ковариантная операция, поэтому тип каждого элемента списка выводится из его источника. Элементы, созданные элементом управления элементами вашего семейства шрифтов (ListBox), являются результатом коллекции, к которой он привязан. Свойство Items (заполняемое с помощью свойства зависимостей ItemsSource) представляет собой коллекцию ItemCollection универсальных объектов, которые принимают тип своих соответствующих контекстных объектов.

person KodeKreachor    schedule 17.03.2012
comment
Я узнаю больше о контравариантных операциях. Спасибо! - person Jazimov; 18.03.2012
comment
Вот хорошая ссылка на ковариацию и контравариантность в C #: blogs.msdn.com/b/csharpfaq/archive/2010/02/16/ - person KodeKreachor; 18.03.2012