2010-07-23 6 views
9

Mam kontrolkę TreeView i chcę powiązać właściwości węzłów drzewa "IsExpanded z moimi DataSource przedmiotami!Treeview Silverlight. Nie można powiązać właściwości "IsExpanded"

Mam jednak wyjątek:

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: 

wewnętrzny wyjątek:

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

a dane elementy:

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

Wersja zestawu SDK i zestawu narzędzi? Co cię przekonuje, że ma to coś wspólnego z własnością "IsExpanded"? Jeśli usuniesz 'ItemContainerStyle', czy wyjątek zniknie? – AnthonyWJones

+1

"Jeśli usuniesz ItemContainerStyle, czy wyjątek zniknie?" Tak! wyjątek odejdź! Toolkit: http://www.microsoft.com/silverlight/ – Evgeny

Odpowiedz

7

Najszybszym sposobem jest podklasy zarówno TreeView i TreeViewItem, na przykład:

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

Niestety stracisz domyślny Skórki z TreeView po wykonaniu podklasy. To słabość koncepcji tematycznej Silverlight. W ten sposób można alternatywnie użyć niestandardowego obiektu Attached Property lub Behavior the tree i ustawia wiązania z zewnątrz. Ponieważ węzły drzewa są tworzone leniwie na żądanie, należy jednak raz usłyszeć zdarzenie Expanded dla każdego węzła, który nie został jeszcze wyrenderowany, a następnie ustawić powiązania w tej procedurze obsługi zdarzeń dla każdego z jego elementów potomnych po oczekiwaniu na Przełęcz układu.

+1

SetBinding nie przyjmuje 1 argumentu! – Evgeny

+2

@ Jewgienij ooops, moje złe ...edytował odpowiedź, aby dodać brakujące argumenty do wywołań metod .SetBinding (...). – herzmeister

4

Chciałem tylko podkreślić, że jest to teraz możliwe. Używam Silverlight 5, wraz z Toolkitem Silverlight skompilowanym na SL5 i możesz powiązać IsExpanded. Zdefiniowałem styl w nieco innym miejscu niż ty. Oto mój 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> 

W przypadku, gdy zastanawiasz się, wiązanie SelectedItem nie dać ostrzeżenie (jak to jest wciąż tylko do odczytu własnością TreeView).

Naprawdę nie chciałem przywołać starego wątku, ale był to najnowszy, który zobaczyłem na ten temat i uznałem, że przydatne byłoby, gdyby ludzie wiedzieli, że to działa.

+0

Dzięki za tę aktualizację, ale dla mnie to nie zadziałało. Zobacz moją odpowiedź poniżej. – Rogier

1

Aby śledzić Malcom, udało mi się go użyć zamiast Item5Lux zamiast 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

Jeśli używasz SL5, standardowe szablony XAML powinny działać. Ale jeśli używasz SL4 lub poniżej, będziesz musiał użyć SetterValueBindingHelper z here. Twój XAML będzie wyglądał następująco. Upewnij się, że dokładnie kopiujesz to, co mam poniżej.

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

Składnia nie jest dokładnie taka, jak w przypadku WPF, ale działa i działa dobrze!