2010-07-23 1 views
9

У меня есть TreeView управление, и я хочу привязать дерево узлов IsExpanded к моим DataSource элементам!Silverview treeview. Не удается связать свойство IsExpanded

Но у меня есть исключение:

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

Версия SDK и Toolkit? Что вас убеждает в том, что это имеет какое-либо отношение к свойству IsExpanded? Если вы удалите «ItemContainerStyle», исключение исчезнет? – AnthonyWJones

+1

«Если вы удалите ItemContainerStyle, исключение исчезнет?» Да! исключение уходит! Инструментарий: http://www.microsoft.com/silverlight/ – Evgeny

ответ

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

SetBinding не принимает 1 аргумент! – Evgeny

+2

@ Evgeny ooops, мой плохой ...отредактировал ответ, чтобы добавить отсутствующие аргументы в вызовы метода .SetBinding (...). – herzmeister

4

Я просто хотел указать, что теперь это возможно. Я использую Silverlight 5 вместе с Silverlight Toolkit, скомпилированным против SL5, и вы можете привязываться к 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).

На самом деле не хотелось поднимать старую нить, но это был самый последний из них, который я видел по этой теме, и почувствовал, что людям полезно знать, что это действительно работает.

+0

Спасибо за это обновление, но для меня это не сработало. См. Мой ответ ниже. – Rogier

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

Если вы используете SL5, тогда стандартные устройства XAML должны работать. Но, если вы используете SL4 или ниже, вам нужно будет использовать SetterValueBindingHelper от here. Тогда ваш 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, но он работает, и он работает хорошо!