Привязка ElementName нарушена в ControlTemplate
Вопрос
У меня есть ListView с группировкой элементов.Для группировки используется собственный GroupStyle (Expander).Я хотел бы иметь флажок, который будет разворачивать и сворачивать все группы, когда.Это работает нормально, пока я не нажму вручную на заголовок группы и не разверну или не сверну эту группу.После нажатия на эту конкретную группу перестает реагировать на установку флажка.Похоже, привязка нарушена после того, как пользователь вручную щелкнул группу.
Посоветуйте, пожалуйста, что я делаю не так.
Большое спасибо.
С уважением, Влад.
<Window xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<Window.Resources>
<XmlDataProvider x:Key="MyData" XPath="/Info">
<x:XData>
<Info xmlns="">
<Item Name="Item 1" Category="Cat1" />
<Item Name="Item 2" Category="Cat1" />
<Item Name="Item 3" Category="Cat2" />
<Item Name="Item 4" Category="Cat2" />
<Item Name="Item 5" Category="Cat2" />
<Item Name="Item 6" Category="Cat3" />
</Info>
</x:XData>
</XmlDataProvider>
<CollectionViewSource x:Key='src' Source="{Binding Source={StaticResource MyData}, XPath=Item}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="@Category" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<ControlTemplate x:Key="ListTemplate" TargetType="ListView">
<ListView BorderThickness="0"
ItemsSource='{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ItemsSource}'
DisplayMemberPath="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DisplayMemberPath}">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,5" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="{Binding IsChecked, ElementName=chkExpandAll, Mode=OneWay}">
<Expander.Header>
<DockPanel>
<TextBlock FontWeight="Bold" Text="{Binding Path=Name}" Margin="5,0,0,0" Width="100" />
<TextBlock FontWeight="Bold" Text="{Binding Path=ItemCount}" />
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<CheckBox Name="chkExpandAll" IsChecked="True" Content="Expand All" />
<ListView ItemsSource='{Binding Source={StaticResource src}}' DisplayMemberPath="@Name" BorderThickness="1" Template="{StaticResource ListTemplate}" />
</StackPanel>
</Window>
Решение
Я нашел решение проблемы.Что нужно сделать, так это указать Mode=TwoWay и UpdateSourceTrigger=Explicit, чтобы таким образом не нарушалась привязка и все работало нормально.Ниже приведен пример рабочего кода.
<Window xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<Window.Resources>
<XmlDataProvider x:Key="MyData" XPath="/Info">
<x:XData>
<Info xmlns="">
<Item Name="Item 1" Category="Cat1" />
<Item Name="Item 2" Category="Cat1" />
<Item Name="Item 3" Category="Cat2" />
<Item Name="Item 4" Category="Cat2" />
<Item Name="Item 5" Category="Cat2" />
<Item Name="Item 6" Category="Cat3" />
</Info>
</x:XData>
</XmlDataProvider>
<CollectionViewSource x:Key='src' Source="{Binding Source={StaticResource MyData}, XPath=Item}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="@Category" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<ControlTemplate x:Key="ListTemplate" TargetType="ListView">
<ListView BorderThickness="0"
ItemsSource='{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ItemsSource}'
DisplayMemberPath="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DisplayMemberPath}">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,5" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<StackPanel>
<Expander Name="exp" IsExpanded="{Binding IsChecked, ElementName=chkExpandAll, Mode=TwoWay, UpdateSourceTrigger=Explicit}">
<Expander.Header>
<DockPanel>
<TextBlock FontWeight="Bold" Text="{Binding Path=Name}" Margin="5,0,0,0" Width="100" />
<TextBlock FontWeight="Bold" Text="{Binding Path=ItemCount}" />
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<CheckBox Name="chkExpandAll" Content="Expand All" />
<ListView ItemsSource='{Binding Source={StaticResource src}}' DisplayMemberPath="@Name" BorderThickness="1" Template="{StaticResource ListTemplate}" />
</StackPanel>
</Window>
Другие советы
Похоже, что привязка нарушена, поскольку с помощью флажка установлено значение OneWay, а затем, если вы щелкнете по любому из расширителей, привязка разорвется.Установка значения TwoWay приведет к тому, что он будет работать всегда, но расширение одного элемента приведет к расширению их всех, что не очень полезно.
Я считаю, что решением этой проблемы будет не использовать привязки, а использовать раскадровки.Вы можете запустить раскадровку, которая приведет к тому, что для всех расширителей будет установлено значение true/false, независимо от их текущего состояния.Однако обновление флажка может быть сложнее, поскольку требуется некоторая логика, чтобы увидеть, все ли флажки отмечены или только некоторые.