0

我想要实现的目标:折叠或展开在组样式中共享相同组名的所有扩展器。

我们有一个 ListBox 和另一个嵌套在其中的 ListBox 以显示子项。子项 ItemsSource 绑定到 CollectionView 并附加了组描述。

组项模板非常简单:

<Expander IsExpanded="{Binding Path=WHAT_TO_DO, Mode=TwoWay}">
                <Expander.Header>
                    <TextBlock Text="{Binding Name}" />
                </Expander.Header>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" SharedSizeGroup="{Binding Name, Converter={StaticResource GroupNameToUniqueNameConverter}}" />
                    </Grid.RowDefinitions>
                    <ItemsPresenter/>
                </Grid>
            </Expander>
4

3 回答 3

1

我认为这不是那么容易做到的。这里可能有两种选择

1)手动 - 绑定您需要的每个扩展器,例如。组中的第一项或任何其他适当的项。

2)更自动的方式可能需要编写一个类,该类具有一个保存每个组状态的字典。这里的问题是控制器需要知道扩展器的哪个实例正在执行绑定或它在哪个组中。我在这里看到的一个解决方案是编写一个自定义转换器,该转换器具有带字典的类的静态实例并使用转换器传递组/引用的参数(您可以在此处使用绑定,因此在 xaml 中这是纯 Ctrl+C、Ctrl+V 操作)

于 2010-07-02T11:48:24.077 回答
0

您可以在代码后面遍历所有列表框项。对于每个列表框项目,您应该查看它是否包含扩展器。如果是这样,您只需展开或折叠它。有关如何迭代项目和查找特定控件的信息,请参阅此链接。

有没有办法在 ListBox Items 模板中进行迭代?

于 2010-07-02T12:46:28.767 回答
0

创建您自己的控件 - GroupExpander - 从 Expander 子类化它

使用以下辅助方法查找可视层次结构中的任何父项:

    public static IEnumerable<T> RecurseParents<T>(this DependencyObject child)
    {
        if (child is T)
        {
            yield return Get<T>(child);
        }

        if (child != null)
        {
            foreach (var parent in RecurseParents<T>(child.GetParentObject()))
            {
                yield return parent;
            }
        }
    }

    public static DependencyObject GetParentObject(this DependencyObject child)
    {
        if (child == null) return null;

        // handle content elements separately
        var contentElement = child as ContentElement;
        if (contentElement != null)
        {
            var parent = ContentOperations.GetParent(contentElement);
            if (parent != null) return parent;

            var fce = contentElement as FrameworkContentElement;
            return fce != null ? fce.Parent : null;
        }

        // also try searching for parent in framework elements (such as DockPanel, etc)
        var frameworkElement = child as FrameworkElement;
        if (frameworkElement != null)
        {
            var parent = frameworkElement.Parent;
            if (parent != null) return parent;
        }

        // if it's not a ContentElement/FrameworkElement, rely on VisualTreeHelper
        return VisualTreeHelper.GetParent(child);
    }

现在通过查找父扩展器并计算这是哪个扩展器来编写查找 GroupExpander 级别的逻辑

你可以从下面的代码中得到这个想法:

public class DataGridGroupExpander : GroupExpander
{
    #region Class level variables

    private bool mSettingIsExpanded = false;

    #endregion

    #region Constructors

    public DataGridGroupExpander()
    {
        SetBinding(HeaderProperty, new Binding("Name"));

        Loaded += DataGridGroupExpander_Loaded;
    }

    #endregion

    #region Properties

    #region Owner

    private DataGrid mOwner = null;
    public DataGrid Owner
    {
        get { return mOwner; }
        private set
        {
            if (mOwner != value)
            {
                if (mOwner != null)
                {
                    DetachOwner();
                }
                mOwner = value;
                if (mOwner != null)
                {
                    AttachOwner();
                }
            }
        }
    }

    private void AttachOwner()
    {
        SetFieldName();
    }

    private void DetachOwner()
    {

    }

    #endregion

    #region ParentExpander

    private DataGridGroupExpander mParentExpander = null;
    public DataGridGroupExpander ParentExpander
    {
        get { return mParentExpander; }
        private set
        {
            if (mParentExpander != value)
            {
                if (mParentExpander != null)
                {
                    DetachParentExpander();
                }
                mParentExpander = value;
                if (mParentExpander != null)
                {
                    AttachParentExpander();
                }
            }
        }
    }

    private void AttachParentExpander()
    {
        SetBinding(ParentExpanderLevelProperty, new Binding("Level") { Source = ParentExpander });
    }

    private void DetachParentExpander()
    {
        ClearValue(ParentExpanderLevelProperty);
    }

    #endregion

    #endregion

    #region Event handlers

    private void DataGridGroupExpander_Loaded(object sender, System.Windows.RoutedEventArgs e)
    {
        ParentExpander =  this.RecurseParents<DataGridGroupExpander>().Skip(1).Take(20).FirstOrDefault();
        Owner = this.RecurseParents<DataGrid>().FirstOrDefault();
        LoadGroupIsExpandedState();
    }

    #endregion

    #region Methods

    private void LoadGroupIsExpandedState()
    {
        if (!mSettingIsExpanded && Owner != null)
        {
            mSettingIsExpanded = true;
            try
            {
                IsExpanded = Owner.LoadGroupIsExpandedState(Header);
            }
            finally
            {
                mSettingIsExpanded = false;
            }
        }
    }

    private void PersistGroupIsExpandedState()
    {
        if (!mSettingIsExpanded && Owner != null)
        {
            Owner.PersistGroupIsExpandedState(Header, IsExpanded);
        }
    }

    private void SetFieldName()
    {
        var fieldName = "";
        if (Owner != null && Owner.Items != null && Owner.Items.GroupDescriptions.Count > Level)
        {
            var groupDescription = Owner.Items.GroupDescriptions[Level] as PropertyGroupDescription;
            if(groupDescription!=null)
            {
                fieldName = groupDescription.PropertyName;
            }
        }
        SetValue(FieldNameKey, fieldName);
    }

    #endregion

    #region Overrides

    tected override void HeaderUpdated()
    {
        LoadGroupIsExpandedState();
    }

    tected override void IsExpandedUpdated()
    {
        PersistGroupIsExpandedState();
    }

    #endregion

    #region Dependency Properties

    #region ParentExpanderLevel

    public int ParentExpanderLevel
    {
        get { return (int)GetValue(ParentExpanderLevelProperty); }
        set { SetValue(ParentExpanderLevelProperty, value); }
    }

    public static readonly System.Windows.DependencyProperty ParentExpanderLevelProperty =
        System.Windows.DependencyProperty.Register(
            "ParentExpanderLevel",
            typeof(int),
            typeof(DataGridGroupExpander),
            new System.Windows.PropertyMetadata(-1, OnParentExpanderLevelPropertyChanged));

    private static void OnParentExpanderLevelPropertyChanged(System.Windows.DependencyObject sender, System.Windows.DependencyPropertyChangedEventArgs e)
    {
        var control = sender as DataGridGroupExpander;
        if (control != null)
        {
            control.ParentExpanderLevelUpdated();
        }
    }

    private void ParentExpanderLevelUpdated()
    {
        SetValue(LevelKey, ParentExpanderLevel + 1);
    }

    #endregion

    #region Level

    public int Level
    {
        get { return (int)GetValue(LevelProperty); }
    }

    internal static readonly DependencyPropertyKey LevelKey = DependencyProperty.RegisterReadOnly(
          "Level",
          typeof(int),
          typeof(DataGridGroupExpander),
          new System.Windows.PropertyMetadata(0, OnLevelPropertyChanged));

    public static readonly DependencyProperty LevelProperty = LevelKey.DependencyProperty;

    private static void OnLevelPropertyChanged(System.Windows.DependencyObject sender, System.Windows.DependencyPropertyChangedEventArgs e)
    {
        var control = sender as DataGridGroupExpander;
        if (control != null)
        {
            control.LevelUpdated();
        }
    }

    private void LevelUpdated()
    {
        SetFieldName();
    }

    #endregion

    #region FieldName

    public string FieldName
    {
        get { return (string)GetValue(FieldNameProperty); }
    }

    internal static readonly DependencyPropertyKey FieldNameKey = DependencyProperty.RegisterReadOnly(
          "FieldName",
          typeof(string),
          typeof(DataGridGroupExpander),
          new PropertyMetadata(null, OnFieldNamePropertyChanged));

    public static readonly DependencyProperty FieldNameProperty = FieldNameKey.DependencyProperty;

    private static void OnFieldNamePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var control = sender as DataGridGroupExpander;
        if (control != null)
        {
            control.FieldNameUpdated();
        }
    }

    private void FieldNameUpdated()
    {

    }

    #endregion

    #endregion
}
于 2011-09-08T08:41:47.787 回答