views:

263

answers:

1

I have treeview control and i want bind tree nodes IsExpanded property to my datasource items!

But i have exception:

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:

inner exception:

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

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

and data items:

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

The quickest way is to subclass both the TreeView and the TreeViewItem something like that:

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

Unfortunately you'll lose the default theming of the TreeView when you do the subclassing. That is a weakness of the Silverlight theming concept. Thus you could alternatively use a custom Attached Property that traverses the tree, listens to the Expanded events and sets the bindings there.

herzmeister der welten
SetBinding doesnot take 1 argument!
Evgeny
@Evgeny ooops, my bad... edited the answer to add the missing arguments to the .SetBinding(...) method calls.
herzmeister der welten