2010-07-23 11 views
9

Tengo el control TreeView y quiero vincular la propiedad IsExpanded de los nodos del árbol a mis DataSource elementos.Silverlight treeview. No se puede enlazar la propiedad "IsExpanded"

Pero tengo una excepción:

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: 

excepción interna:

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

y los datos de artículos:

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

¿Versión de SDK y Toolkit? ¿Qué te convence de que esto tiene algo que ver con la propiedad 'IsExpanded'? Si elimina el 'ItemContainerStyle', ¿la excepción desaparecerá? – AnthonyWJones

+1

"Si elimina ItemContainerStyle, ¿se va la excepción?" ¡Sí! excepción desaparece! Toolkit: http://www.microsoft.com/silverlight/ – Evgeny

Respuesta

7

La forma más rápida es la subclase tanto el TreeView y la TreeViewItem, por ejemplo:

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

desgracia si no se pierden la tematización por defecto de la TreeView cuando lo hace la subclasificación. Esa es una debilidad del concepto de tematización de Silverlight. Por lo tanto, podría utilizar alternativamente una propiedad adjunta adjunta o una Comportamiento que atraviesa el árbol y establece los enlaces desde el exterior. Sin embargo, debido a que los nodos de árbol se crean perezosamente a pedido, debe escuchar el evento Expanded una vez por cada nodo que aún no se ha renderizado, luego establecer los enlaces en ese controlador de eventos para cada uno de sus hijos después de esperar el Pase de diseño.

+1

¡SetBinding no toma 1 argumento! – Evgeny

+2

@Evgeny ooops, mi mal ...editó la respuesta para agregar los argumentos faltantes a las llamadas al método .SetBinding (...). – herzmeister

4

Solo quería señalar que esto ahora es posible. Estoy usando Silverlight 5, junto con Silverlight Toolkit compilado contra SL5 y puede enlazar a IsExpanded. Definí el estilo en un lugar ligeramente diferente a ti. Aquí está mi 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> 

En caso de que se preguntan, la unión SelectedItem da una advertencia (ya que sigue siendo una propiedad de sólo lectura de TreeView).

Realmente no quería mostrar un hilo viejo, pero este fue el más reciente que vi sobre este tema y sentí que sería útil para la gente saber que de hecho funciona.

+0

Gracias por esta actualización, pero para mí esto no funcionó. Ver mi respuesta a continuación. – Rogier

1

Para realizar un seguimiento en Malcom, lo hice funcionar con ItemContainerStyle en lugar de 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> 
1

Si está utilizando SL5, entonces los ajustadores XAML estándar deberían funcionar. Pero, si está utilizando SL4 o menos, necesitará usar SetterValueBindingHelper de here. Entonces su XAML tendrá el siguiente aspecto. Asegúrate de copiar cuidadosamente lo que tengo a continuación.

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

La sintaxis no es exactamente igual a la que se uso en WPF, pero funciona y funciona bien!

Cuestiones relacionadas