【问题标题】:Silverlight treeview. Cannot bind "IsExpanded" propertySilverlight 树视图。无法绑定“IsExpanded”属性
【发布时间】:2010-07-23 08:40:26
【问题描述】:

我有TreeView 控件,我想将树节点的IsExpanded 属性绑定到我的DataSource 项目!

但我有一个例外:

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;};
}

【问题讨论】:

  • SDK 和工具包的版本?是什么让您相信这与 IsExpanded 属性有关?如果您删除 ItemContainerStyle,异常会消失吗?
  • "如果您删除 ItemContainerStyle,异常会消失吗?"是的!异常走开!工具包:microsoft.com/silverlight

标签: wpf silverlight data-binding treeview


【解决方案1】:

最快的方法是同时继承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 主题概念的一个弱点。因此,您可以选择使用自定义 Attached PropertyBehavior 遍历树并从外部设置绑定。由于树节点是按需延迟创建的,因此您必须为每个尚未呈现的节点侦听一次 Expanded 事件,然后在等待后为其每个子节点设置该事件处理程序中的绑定用于布局通道。

【讨论】:

  • SetBinding 不接受 1 个参数!
  • @Evgeny 哎呀,我的错...编辑了答案以将缺少的参数添加到 .SetBinding(...) 方法调用中。
【解决方案2】:

我只是想指出,现在这是可能的。我正在使用 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 的只读属性)。

我真的不想提出一个旧帖子,但这是我最近看到的关于这个主题的帖子,我觉得让人们知道它确实有效会很有用。

【讨论】:

  • 感谢这次更新,但对我来说这不起作用。请参阅下面的答案。
【解决方案3】:

为了跟进 Malcom,我使用 ItemContainerStyle 代替 SL5 让它工作。

    <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>

【讨论】:

    【解决方案4】:

    如果您使用的是 SL5,那么标准的 XAML 设置器应该可以工作。但是,如果您使用的是 SL4 或更低版本,则需要使用来自 hereSetterValueBindingHelper。然后您的 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 中使用的语法不完全一样,但它可以工作,而且效果很好!

    【讨论】:

      猜你喜欢
      • 2021-04-04
      • 2011-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-27
      • 1970-01-01
      • 2013-03-26
      • 1970-01-01
      相关资源
      最近更新 更多