WPF ListBox ListBoxItem Binding - PullRequest
       30

WPF ListBox ListBoxItem Binding

4 голосов
/ 18 марта 2012

Я изучаю книгу Самса «Обучайся WPF за 24 часа».В какой-то момент авторы показывают, как можно привязать значение выбранного элемента 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" />

Обратите внимание, что путь установлен в 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" />

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

<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" />

Я вижу, что оно меняется, когда я нажимаю на Размер 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 в виде текста.Если ссылка Path моего ListBox возвращает объект SelectedItem типа ListBoxItem, то я думаю, что я мог бы использовать Path of SelectedItem.Value или что-то в этом роде - но это не работает, и нет Intellisense, чтобы помочь мне.

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

Ответы [ 2 ]

2 голосов
/ 18 марта 2012

Какое фактическое значение возвращается путем, называемым 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 (хотя они все еще создаются для представления каждого элемента в коллекции). Вы можете добиться того же поведения с размерами шрифтов, если определите набор размеров шрифтов в коде и свяжете свойство ItemsSource ListBox с этой коллекцией или определите содержимое вашего 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>
1 голос
/ 18 марта 2012

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

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

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

...