C# 扩展绑定

C# 扩展绑定,c#,.net,wpf,mvvm,C#,.net,Wpf,Mvvm,在以下代码中: 如何将IsExpanded绑定到MyData对象列表,其中每个对象都具有IsExpanded属性 <Expander IsExpanded={Binding Path=IsExpanded, Mode=TwoWay} /> 这不行 MyData is List<GroupNode>; MyData是列表; GroupNode是一个包含notify属性changed属性IsExpanded的类 因此,如果我手动打开一个扩展器,它应该将MyData

在以下代码中:

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

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

这不行

MyData is List<GroupNode>;
MyData是列表;
GroupNode是一个包含notify属性changed属性IsExpanded的类


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

这不是很容易做到,因为
GroupItem的
DataContext
是的一个实例,而这个类没有
IsExpanded
属性。但是,您可以在
GroupDescription
中指定一个转换器,允许您为组的“name”返回自定义值(“code>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>

这不是很容易做到,因为
GroupItem
DataContext
是的一个实例,并且这个类没有
IsExpanded
属性。但是,您可以在
GroupDescription
中指定一个转换器,允许您为组的“name”返回自定义值(“code>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>


如果这个扩展器的datacontext是一个具有称为IsExpanded的布尔属性的对象,那么它可以工作:)那么扩展器的datacontext是什么呢?您希望扩展器表现出什么样的行为?我想我们需要更多的上下文,比如周围的XAML和视图模型的片段。如果该组被扩展,我想将MyData的每个对象的IsExpanded boolean属性设置为true,因此,如果我重置数据,我可以将这些节点的isExpanded设置回true。我相信社区最终将能够回答这个问题,但你越早学会使用或类似的工具,效果越好。它将以红色突出显示损坏的绑定,并告诉您绑定错误是什么。在没有类似工具的情况下调试WPF不会很有趣。@默认情况下,您提醒我忘记了我的标准WPF数据绑定注释:您需要做的第一件事是打开用于数据绑定的调试消息:下一步,重新运行并检查“输出”窗口,查看有哪些错误。如果此扩展器的datacontext是一个具有称为IsExpanded的布尔属性的对象,则可以工作:)那么扩展器的datacontext是什么?您希望扩展器表现出什么样的行为?我想我们需要更多的上下文,比如周围的XAML和视图模型的片段。如果该组被扩展,我想将MyData的每个对象的IsExpanded boolean属性设置为true,因此,如果我重置数据,我可以将这些节点的isExpanded设置回true。我相信社区最终将能够回答这个问题,但你越早学会使用或类似的工具,效果越好。它将以红色突出显示损坏的绑定,并告诉您绑定错误是什么。在没有类似工具的情况下调试WPF不会有意思。@默认情况下,您提醒我忘记了标准WPF数据绑定注释:您需要做的第一件事是打开用于数据绑定的调试消息:接下来,重新运行并检查输出窗口,看看有什么错误。这并不简单,而且会使我的代码在很多地方变得复杂。我不确定这是否是解决这个问题的唯一办法。没有办法用FindAncestor绑定它?是的,我知道它不理想。。。但至少它起作用了。我还没有找到更好的方法。我不确定使用FindAncestor的绑定将如何帮助您。。。每个小组都需要绑定到不同的对象,所以我不知道你打算如何做。我正在为这个问题寻找解决方案,已经有几个小时了(到目前为止,我对WPF不是很有经验)。大约一个小时前,我想和你一样做,但后来决定继续寻找更清洁的解决方案。似乎没有,但现在我感觉有点自信了。(让我们看看代码审阅者是否会接受它)这并不简单,而且会使我的代码在很多地方变得复杂。我不确定这是否是解决这个问题的唯一办法。没有办法用FindAncestor绑定它?是的,我知道它不理想。。。但至少它起作用了。我还没有找到更好的方法。我不确定使用FindAncestor的绑定将如何帮助您。。。每个小组都需要绑定到不同的对象,所以我不知道你打算如何做。我正在为这个问题寻找解决方案,已经有几个小时了(到目前为止,我对WPF不是很有经验)。大约一个小时前,我想和你一样做,但后来决定继续寻找更清洁的解决方案。似乎没有,但现在我感觉有点自信了。(让我们看看代码审阅者是否会接受它)