I have TreeView
control and I want to bind tree nodes' IsExpanded
property to my DataSource
items!
But I have an 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 ''.
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>
and the data items:
public interface INode
{
NodeType Type { get; set; }
bool IsSelected { get; set; }
bool IsExpanded { get; set; }
List<INode> Children{get;set;};
}
The quickest way is to subclass both the TreeView
and the TreeViewItem
, for example:
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 or a Behavior that traverses the tree and sets the bindings from outside. Because the tree nodes are created lazily on-demand though, you'd have to listen to the Expanded
event once for each node that has not yet been rendered, then set the bindings in that event handler for each of its children after waiting for the layout pass.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With