我有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;};
}
答案 0 :(得分:7)
最快捷的方法是对TreeView
和TreeViewItem
进行子类化,例如:
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 :(得分: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的只读属性)。
我真的不想提出一个旧帖子,但这是我在这个主题上看到的最新内容,并认为人们知道它确实有效。
答案 2 :(得分:1)
为了跟进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>
答案 3 :(得分: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中使用的语法不完全相同,但它的工作原理并且运行良好!