2010-07-23 18 views
9

Ho il controllo TreeView e desidero associare i nodi degli alberi 'IsExpanded ai miei articoli DataSource!Treeview Silverlight. Impossibile associare la proprietà "IsExpanded"

Ma ho un'eccezione:

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: 

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

ei dati oggetti:

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

Versione di SDK e Toolkit? Cosa ti convince che questo ha qualcosa a che fare con la proprietà 'IsExpanded'? Se rimuovi il 'ItemContainerStyle', l'eccezione scompare? – AnthonyWJones

+1

"Se rimuovi ItemContainerStyle, l'eccezione scompare?" Sì! l'eccezione va via! Toolkit: http://www.microsoft.com/silverlight/ – Evgeny

risposta

7

Il modo più veloce è quello di creare una sottoclasse sia il TreeView e TreeViewItem, ad esempio:

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

Purtroppo si perde la tematizzazione di default del TreeView quando si esegue la creazione di sottoclassi. Questa è una debolezza del concetto di tematica di Silverlight. In alternativa, è possibile utilizzare una proprietà allegata o un Comando personalizzato che attraversa l'albero e imposta i binding dall'esterno. Poiché i nodi ad albero vengono creati pigramente su richiesta, dovresti ascoltare l'evento Expanded una volta per ogni nodo che non è ancora stato reso, quindi impostare i binding in quel gestore eventi per ciascuno dei suoi figli dopo aver atteso il passaggio di layout.

+1

SetBinding non accetta 1 argomento! – Evgeny

+2

@Evgeny ooops, il mio cattivo ...modificato la risposta per aggiungere gli argomenti mancanti alle chiamate al metodo .SetBinding (...). – herzmeister

4

Volevo solo far notare che ora è possibile. Sto utilizzando Silverlight 5, insieme a Silverlight Toolkit compilato su SL5 e puoi eseguire il binding a IsExpanded. Ho definito lo stile in un posto leggermente diverso da te. Ecco il mio 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> 

Nel caso ve lo stiate chiedendo, il legame SelectedItem fa dare un avvertimento (come è ancora una proprietà di sola lettura di TreeView).

Non volevo davvero aprire un thread vecchio, ma questo è stato il più recente che ho visto su questo argomento e ho ritenuto che sarebbe stato utile per le persone sapere che effettivamente funziona.

+0

Grazie per questo aggiornamento, ma per me questo non ha funzionato. Vedi la mia risposta qui sotto. – Rogier

1

Per eseguire il follow up su Malcom, ho avuto modo di funzionare utilizzando ItemContainerStyle invece con 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

Se si utilizza SL5, i setter XAML standard dovrebbero funzionare. Tuttavia, se si utilizza SL4 o inferiore, sarà necessario utilizzare SetterValueBindingHelper da here. Quindi il tuo XAML sarà simile al seguente. Assicurati di copiare attentamente quello che ho qui sotto.

<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 sintassi non è esattamente come quello che si usa in WPF, ma funziona e funziona bene!

Problemi correlati