【问题标题】:FindAncestor implementation in WP8 ListBoxWP8 ListBox 中的 FindAncestor 实现
【发布时间】:2014-07-27 16:32:22
【问题描述】:

我想直接实现一个 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 被选中,我想将切换按钮设置为 Checked,否则我想将 IsChecked 设置为 False。

【问题讨论】:

    标签: windows-phone-8 listbox findancestor


    【解决方案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 绑定到 ElementComparer 的 Result,并将comaprer 的 Element1 和 Element2 与当前项和 lboxData (ListBox) 的 SelectedItem 绑定

    <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 属性中删除了一种方式绑定到 ElementComparer 的结果
    • 将 SelectedItem 添加到 ElementComparer 的 Element2 的两种方式
    • 为 ElementComparer 中的 Result 属性添加了属性更改处理程序
    • 当结果发生变化并且为真时(选中切换)将 Element1 的值推送到 Element2
    • 由于 Element2 绑定到 SelectedItem,它会强制其他项目的结果为 false,因此关闭切换并折叠子列表
    • 将 Mode=TwoWay 添加到 toggle 的 IsChecked 属性,因为没有它似乎就无法预测

    附加功能

    此外,如果您不想在列表项中看到难看的蓝色选择,那么您也可以将以下内容添加到您的资源中

    <Style TargetType="ListBoxItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <Border Background="Transparent">
                        <ContentPresenter/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    【讨论】:

    • 我尝试了示例,但在 2 点处出现异常 1. MultiBinding 不是有效的 xaml 标记,并且缺少 IMultiValueConverter 命名空间。我怎样才能覆盖这两个问题?
    • 对以前的方法表示歉意,因为我不知道多重绑定和转换器被排除在 Metro 应用程序之外。我修改了我的解决方案以在没有它的情况下工作,因此这更有可能在 WP8 上工作
    • 是的。但不是完全的,我正在努力让它成为我想要的方式。我会尽快上传详细的问题描述。
    • 我期望列表框的行为方式 - 首先所有主要项目都被折叠(未选中)一旦选择项目(比如列表中的第一个项目),基础项目应该展开。一旦选择了另一个项目(比如列表中的第三个项目),所有其他选定的项目应该折叠并且新项目,即第三个项目应该展开。但现在的行为更像是,起初所有项目都没有被选中。我选择项目 1 ,它会展开它的所有子项目。我选择了第3项,现在第1项和第3项都处于展开状态使用的xaml结构在这里pastebin.com/FJDWRiVu
    • , Mode=TwoWay 也需要切换按钮
    猜你喜欢
    • 2015-03-13
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多