Реализация FindAncestor в WP8 ListBox
Я хочу реализовать привязку Listbox напрямую, и вот код, который я использовал в синтаксисе WPF
<ListBox Name="lboxData" ItemsSource="{Binding}">
<ListBox.ItemTemplate >
<DataTemplate>
<StackPanel>
<ToggleButton x:Name="toggleChild" Style="{StaticResource ChapterHeadingStyle}"
IsChecked="{Binding IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}" // This is what i have to change . I want to set it based on the status of the ListBoxItem & Given code is the one i used in WPF app
/>
<ListBox Visibility="{Binding IsChecked, ElementName=toggleChild, Converter={StaticResource boolToVis}}" ItemsSource="{Binding pages}" Margin="10,0,0,0" >
<ListBox.ItemTemplate >
<DataTemplate>
//here is displaying child items one by one ..
</DataTemplate>
</ListBox.ItemTemplate >
</ListBox>
</ListBox.ItemTemplate >
</DataTemplate>
</StackPanel>
</ListBox>
Проблема в том, что в WP8 RelativeSource = {RelativeSource Mode = FindAncestor, AncestorType = {x: Type ListBoxItem} не поддерживается. Так как я могу добиться того же в WP8. Я хочу установить переключатель как Проверено, если выбран контейнер ListboxItem, иначе я хочу установить IsChecked как False.
1 ответ
Я начну с написания класса сравнения
public class ElementComparer : FrameworkElement
{
public object Element1
{
get { return (object)GetValue(Element1Property); }
set { SetValue(Element1Property, value); }
}
// Using a DependencyProperty as the backing store for Element1. This enables animation, styling, binding, etc...
public static readonly DependencyProperty Element1Property =
DependencyProperty.Register("Element1", typeof(object), typeof(ElementComparer), new PropertyMetadata(null, UpdateResult));
public object Element2
{
get { return (object)GetValue(Element2Property); }
set { SetValue(Element2Property, value); }
}
// Using a DependencyProperty as the backing store for Element2. This enables animation, styling, binding, etc...
public static readonly DependencyProperty Element2Property =
DependencyProperty.Register("Element2", typeof(object), typeof(ElementComparer), new PropertyMetadata(null, UpdateResult));
public bool Result
{
get { return (bool)GetValue(ResultProperty); }
set { SetValue(ResultProperty, value); }
}
// Using a DependencyProperty as the backing store for Result. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ResultProperty =
DependencyProperty.Register("Result", typeof(bool), typeof(ElementComparer), new PropertyMetadata(false, OnResultChanged)); //added changed handler
private static void OnResultChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ElementComparer ec = d as ElementComparer;
//if true then set the element 2 to element 1 of the comparer otherwise null
ec.Element2 = ((bool)e.NewValue) ? ec.Element1 : null;
}
private static void UpdateResult(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ElementComparer ec = d as ElementComparer;
ec.Result = object.ReferenceEquals(ec.Element1, ec.Element2);
}
}
затем я свяжу IsChecked от togglebutton с Result of ElementComparer и свяжу Element1 и Element2 comaprer с текущим элементом и SelectedItem для lboxData (ListBox)
<ListBox Name="lboxData" ItemsSource="{Binding}">
<ListBox.ItemTemplate >
<DataTemplate>
<StackPanel>
<!--added Mode=TwoWay to binding of Element2-->
<local:ElementComparer x:Name="ElementComparer"
Element1="{Binding}"
Element2="{Binding SelectedItem, ElementName=bookTOCBox, Mode=TwoWay}" />
<!--removed Mode=OneWay from binding of IsChecked and added Mode=TwoWay-->
<ToggleButton x:Name="toggleChild" Content="{Binding name}"
Style="{StaticResource ChapterHeadingStyle}"
IsChecked="{Binding Result, ElementName=ElementComparer, Mode=TwoWay}"/>
...
</StackPanel>
хитрость заключается в том, чтобы сравнить выбранный элемент списка с текущим элементом, чтобы определить, выбран ли он, если имя родительского списка "lboxData"
это тоже будет работать в WP8
Обновить сводку
- Убрана односторонняя привязка из свойства IsChecked для переключения на Result of ElementComparer
- Добавлена двухсторонняя привязка к SelectedItem для Element2 ElementComparer
- добавлено изменение свойства обработчика для свойства Result в ElementComparer
- когда результат изменится и будет истинным (переключение проверено), нажмите значение элемента от 1 до 2
- так как Element2 привязан к SelectedItem, он принудительно возвращает результат других элементов в значение false, поэтому отключите переключатель и сверните дочерний список
- добавил свойство =TwoWay к свойству IsChecked переключателя, так как кажется без него непредсказуемым
Дополнительно
Кроме того, если вы не хотите видеть уродливую синюю выделенную область в элементах списка, вы также можете добавить следующее к своим ресурсам.
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Background="Transparent">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>