【问题标题】:Expander IsExpanded bindingExpander IsExpanded 绑定
【发布时间】:2011-05-23 15:10:25
【问题描述】:

在以下代码中:

http://msdn.microsoft.com/en-us/library/ms754027.aspx

如何将 IsExpanded 绑定到 MyData 对象列表,其中每个对象都有 IsExpanded 属性?

<Expander IsExpanded={Binding Path=IsExpanded, Mode=TwoWay} />

这行不通!

MyData is List<GroupNode>;

GroupNode 是一个包含通知属性更改属性 IsExpanded 的类。

因此,如果我手动打开其中一个扩展器,它应该将 MyData 的 GroupNode 的 IsExpanded 属性设置为 true。

【问题讨论】:

  • 如果此 Expander 的数据上下文是一个具有名为 IsExpanded 的布尔属性的对象 - 它会起作用:) 那么您的 Expander 的 DataContext 是什么?你希望扩展器表现什么?
  • 我认为我们需要更多的上下文,比如周围的 XAML 和视图模型的 sn-p。
  • 如果该组展开,我想将 MyData 的每个对象的 IsExpanded 布尔属性设置为 true,这样如果我重置数据,我可以将这些节点的 isExpanded 设置回 true。跨度>
  • 我相信社区最终能够回答这个问题,但是你越早学会使用snoop 或类似的工具越好。它将以红色突出显示损坏的绑定,并告诉您绑定错误是什么。没有这样的工具调试 WPF 不会很有趣。
  • @default 你提醒我我忘记了我的标准 WPF 数据绑定评论:首先你需要做的是打开数据绑定的调试消息:i.imgur.com/UAxJO.png 接下来,重新运行并检查输出窗口并查看有什么错误。

标签: c# .net wpf mvvm


【解决方案1】:

这不是很容易做到,因为GroupItemDataContextCollectionViewGroup 的一个实例,而这个类没有IsExpanded 属性。但是,您可以在GroupDescription 中指定一个转换器,从而允许您为组的“名称”返回一个自定义值(CollectionViewGroup.Name 属性)。这个“名字”可以是任何东西;在您的情况下,您需要它是一个包含组名(例如分组键)并具有 IsExpanded 属性的类:

这是一个例子:

public class ExpandableGroupName : INotifyPropertyChanged
{
    private object _name;
    public object Name
    {
        get { return _name; }
        set
        {
            if (_name != value)
            {
                _name = value;
                OnPropertyChanged("Name");
            }
        }
    }

    private bool? _isExpanded = false;
    public bool? IsExpanded
    {
        get { return _isExpanded; }
        set
        {
            if (_isExpanded != value)
            {
                _isExpanded = value;
                OnPropertyChanged("IsExpanded");
            }
        }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion

    public override bool Equals(object obj)
    {
        return object.Equals(obj, _name);
    }

    public override int GetHashCode()
    {
        return _name != null ? _name.GetHashCode() : 0;
    }

    public override string ToString()
    {
        return _name != null ? _name.ToString() : string.Empty;
    }
}

这是转换器:

public class ExpandableGroupNameConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return new ExpandableGroupName { Name = value };
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var groupName = value as ExpandableGroupName;
        if (groupName != null)
            return groupName.Name;
        return Binding.DoNothing;
    }

    #endregion
}

在 XAML 中,只需将分组声明如下:

<my:ExpandableGroupNameConverter x:Key="groupConverter" />
<CollectionViewSource x:Key='src' 
                      Source="{Binding Source={StaticResource MyData}, 
                               XPath=Item}">
  <CollectionViewSource.GroupDescriptions>
    <PropertyGroupDescription PropertyName="@Catalog" Converter="{StaticResource groupConverter}" />
  </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

然后像这样绑定IsExpanded 属性:

<Expander IsExpanded={Binding Path=Name.IsExpanded} />

【讨论】:

  • 它并不简单,并且会使我的代码在很多地方变得复杂。我不确定这是否是解决问题的唯一方法。没有办法使用 FindAncestor 绑定它?
  • 是的,我知道这并不理想......但至少它有效。我还没有找到更好的方法。
  • 我不确定使用 FindAncestor 的绑定对您有什么帮助...每个组都需要绑定到不同的对象,所以我不知道您打算如何做到这一点跨度>
  • 我正在为这个问题寻找解决方案几个小时(到目前为止,我对 WPF 的经验还不是很丰富)。大约 1 小时前,我想过像你一样做,但后来决定继续寻找更清洁的解决方案。似乎没有,但现在我感觉更有信心了。 (看看code reviewer会不会接受)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-26
  • 1970-01-01
  • 1970-01-01
  • 2013-11-25
  • 2021-04-04
  • 2014-10-12
相关资源
最近更新 更多