银光树形视图。无法绑定“IsExpanded”属性。

9
我有一个TreeView控件,我想将树节点的IsExpanded属性绑定到我的数据源项目!但是我遇到了一个异常:
System.Windows.Markup.XamlParseException occurred
  Message=Set property '' threw an exception.

  StackTrace:
       at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
       at SilverlightTree.BSTreeView.InitializeComponent()
       at SilverlightTree.BSTreeView..ctor()
  InnerException: System.NotSupportedException
       Message=Cannot set read-only property ''.
       StackTrace:
            at MS.Internal.XamlMemberInfo.SetValue(Object target, Object value)
            at MS.Internal.XamlManagedRuntimeRPInvokes.SetValue(XamlTypeToken inType, XamlQualifiedObject& inObj, XamlPropertyToken inProperty, XamlQualifiedObject& inValue)
       InnerException: 

内部异常:

{System.NotSupportedException: Cannot set read-only property ''.

XAML:

<Grid x:Name="LayoutRoot">
    <controls:TreeView Name="treeView" SelectedItemChanged="treeView_SelectedItemChanged"
                       Style="{Binding  TreeViewConnectingLines}" BorderBrush="{x:Null}">
        <controls:TreeView.ItemTemplate>
            <toolkit:HierarchicalDataTemplate ItemsSource="{Binding Children}">
                <StackPanel Orientation="Horizontal"  Background="Transparent">
                    <toolkitDrag:ContextMenuService.ContextMenu>
                        <toolkitDrag:ContextMenu Loaded="ContextMenu_Loaded"
                                                 Opened="ContextMenu_Opened"/>
                    </toolkitDrag:ContextMenuService.ContextMenu>
                    <Image Source="{Binding Path=Type.Icon}"  Width="20" Height="20" />
                    <TextBlock Text="{Binding Path=FullDescription}"   Height="20"
                               TextAlignment="Center" HorizontalAlignment="Center" />
                </StackPanel>
            </toolkit:HierarchicalDataTemplate>
        </controls:TreeView.ItemTemplate>
        <controls:TreeView.ItemContainerStyle>
            <Style TargetType="controls:TreeViewItem">
                <Setter Property="IsExpanded" Value="{Binding IsExpanded}"></Setter>
            </Style>
        </controls:TreeView.ItemContainerStyle>     
    </controls:TreeView>
</Grid>

以及数据项:

public interface INode
{
    NodeType Type { get; set; }
    bool IsSelected { get; set; }
    bool IsExpanded { get; set; }
    List<INode> Children{get;set;};
}

3
SDK和工具包的版本?您如何确信这与“IsExpanded”属性有关?如果删除“ItemContainerStyle”,异常是否消失? - AnthonyWJones
1
如果您移除ItemContainerStyle,异常是否消失了? 是的!异常已经消失了! 工具包:http://www.microsoft.com/silverlight/ - Ievgen
4个回答

6

最快的方法是对 TreeViewTreeViewItem 进行子类化,例如:

public class BindableTreeViewItem : TreeViewItem
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        var itm = new BindableTreeViewItem();
        itm.SetBinding(TreeViewItem.IsExpandedProperty, new Binding("IsExpanded") { Mode = BindingMode.TwoWay });

        return itm;
    }
}

public class BindableTreeView : TreeView
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        var itm = new BindableTreeViewItem();
        itm.SetBinding(TreeViewItem.IsExpandedProperty, new Binding("IsExpanded") { Mode = BindingMode.TwoWay });

        return itm;
    }
}

很遗憾,当你进行子类化时,TreeView的默认主题将会丢失。这是Silverlight主题概念的一个缺点。因此,您可以选择使用自定义附加属性行为来遍历树并从外部设置绑定。但由于树节点是按需惰性创建的,所以您需要为尚未呈现的每个节点侦听一次Expanded事件,然后在等待布局传递后为其每个子项设置绑定。


1
SetBinding 不接受一个参数! - Ievgen
2
@Evgeny 哎呀,我的错...已经编辑答案,添加了缺失的参数到 .SetBinding(...) 方法调用中。 - herzmeister

4

我想指出现在已经可以实现这个功能了。我正在使用Silverlight 5,以及针对SL5编译的Silverlight Toolkit,您可以绑定到IsExpanded。我在定义样式时与您略有不同。以下是我的XAML代码。

<controls:TreeView ItemsSource="{Binding Repository.MajorClasses}" ItemTemplate="{StaticResource TreeviewMajorClassTemplate}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
            <controls:TreeView.Resources>
                <Style TargetType="controls:TreeViewItem">
                    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                </Style>
            </controls:TreeView.Resources>
        </controls:TreeView>

如果您想知道,SelectedItem绑定确实会发出警告(因为它仍然是TreeView的只读属性)。

我并不真正希望提及旧的主题,但这是我在此主题上看到的最近的一个帖子,并且感觉让人们知道它确实有效是有用的。


谢谢这个更新,但是对我来说这不起作用。请看我的回答。 - Rogier

1
如果您正在使用SL5,则标准的XAML设置器应该可以工作。但是,如果您正在使用SL4或更低版本,则需要从here使用SetterValueBindingHelper。然后,您的XAML将如下所示。请确保仔细复制我下面的内容。
<sdk:TreeView.ItemContainerStyle>
    <Style TargetType="sdk:TreeViewItem">
        <Setter Property="local:SetterValueBindingHelper.PropertyBinding">
            <Setter.Value>
                <local:SetterValueBindingHelper>
                    <local:SetterValueBindingHelper Property="IsSelected" Binding="{Binding Mode=TwoWay, Path=IsSelected}"/>
                    <local:SetterValueBindingHelper Property="IsExpanded" Binding="{Binding Mode=TwoWay, Path=IsExpanded}"/>
                </local:SetterValueBindingHelper>
            </Setter.Value>
        </Setter>
    </Style>
</sdk:TreeView.ItemContainerStyle>

语法不完全像WPF中使用的那样,但它有效且表现良好!

1
跟进Malcom的问题,我已经使用SL5中的ItemContainerStyle解决了它。
    <sdk:TreeView.ItemContainerStyle>
        <Style TargetType="sdk:TreeViewItem">
            <Setter Property="IsExpanded" Value="True"/>
            <Setter Property="Visibility" Value="{Binding IsVisible, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
         </Style>
    </sdk:TreeView.ItemContainerStyle>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接