【问题标题】:ElementName Binding Broken in a ControlTemplateControlTemplate 中的 ElementName 绑定损坏
【发布时间】:2010-09-18 15:08:41
【问题描述】:

我有带有分组项目的 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>

【问题讨论】:

    标签: wpf binding


    【解决方案1】:

    看起来绑定已损坏,因为它已使用复选框设置为 OneWay,然后如果您单击任何扩展器,它将中断绑定。将其设置为 TwoWay 将使其始终工作,但扩展一项会导致它们全部扩展,这不是很有用。

    我相信解决此问题的方法是不使用绑定,而是使用情节提要。您可以触发一个故事板,这将导致所有扩展器设置为真/假,而不管它们的当前状态如何。不过,更新复选框可能会比较棘手,因为需要一些逻辑来查看是选中了所有复选框还是仅选中了一些复选框。

    【讨论】:

    • 感谢您的回复,您有如何通过 Storyboard 进行操作的示例吗?您可以使用我的示例,它在 XAMLPad 和 KAXAML 中工作,只需复制和粘贴即可。我也不了解更新复选框。我在顶部只有一个复选框,它应该展开所有扩展器或将它们全部折叠。我不认为我需要担心如何更新它。再次感谢。此致,弗拉德。
    【解决方案2】:

    我找到了问题的解决方案。需要做的是指定 Mode=TwoWay 和 UpdateSourceTrigger=Explicit,这样就不会破坏 Binding 并且一切正常。 Bellow 是一个工作代码示例。

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

    【讨论】:

    • 对我来说也一样。在出现 RuntimeException 时,我还被要求指定路径。我将它设置为 path=. 这是我在 ErrorTemplate 中的绑定 PlacementTarget="{Binding ElementName=ImageAction, Path=., Mode=TwoWay, UpdateSourceTrigger=Explicit}" 元素 ImageAction 是一个自定义控件,并且添加方式与示例中的 chkExpandAll 相同。
    猜你喜欢
    • 2013-02-23
    • 2023-04-08
    • 1970-01-01
    • 2010-11-04
    • 2012-07-14
    • 2012-08-26
    • 2015-09-02
    • 2012-02-25
    • 2012-10-12
    相关资源
    最近更新 更多