2010-07-23 6 views
9

Tôi có kiểm soát TreeView và tôi muốn liên kết các thuộc tính của nút cây 'IsExpanded với các mục DataSource của tôi!Xem trước bằng bạc. Không thể liên kết thuộc tính "IsExpanded"

Nhưng tôi có một ngoại lệ:

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: 

nội ngoại lệ:

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

và các dữ liệu mục:

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

Phiên bản SDK và Bộ công cụ? Điều gì thuyết phục bạn rằng điều này có liên quan đến thuộc tính 'IsExpanded'? Nếu bạn loại bỏ 'ItemContainerStyle' thì ngoại lệ có biến mất không? – AnthonyWJones

+1

"Nếu bạn loại bỏ ItemContainerStyle thì ngoại lệ có biến mất không?" Có! ngoại lệ biến mất! Bộ công cụ: http://www.microsoft.com/silverlight/ – Evgeny

Trả lời

7

Cách nhanh nhất là để phân lớp cả TreeViewTreeViewItem, ví dụ:

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

Đáng tiếc là bạn sẽ mất theming mặc định của TreeView khi bạn làm như subclassing. Đó là một điểm yếu của khái niệm themlight Silverlight. Do đó, bạn có thể sử dụng tùy chọn Thuộc tính được đính kèm hoặc Hành vi đi qua cây và đặt các ràng buộc từ bên ngoài. Bởi vì các nút cây được tạo ra một cách uể oải theo yêu cầu, bạn phải nghe sự kiện Expanded một lần cho mỗi nút chưa được hiển thị, sau đó đặt các ràng buộc trong trình xử lý sự kiện đó cho mỗi con của nó sau khi đợi bố trí vượt qua.

+1

SetBinding doesnot mất 1 đối số! – Evgeny

+2

@Evgeny ooops, xấu của tôi ...chỉnh sửa câu trả lời để thêm các đối số còn thiếu vào các cuộc gọi phương thức .SetBinding (...). – herzmeister

4

Tôi chỉ muốn chỉ ra rằng điều này hiện khả thi. Tôi đang sử dụng Silverlight 5, cùng với Silverlight Toolkit được biên dịch với SL5 và bạn có thể liên kết với IsExpanded. Tôi đã xác định phong cách ở một nơi hơi khác so với bạn. Đây là XAML của tôi.

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

Trong trường hợp bạn thắc mắc, ràng buộc SelectedItem đưa ra cảnh báo (vì nó vẫn là thuộc tính chỉ đọc của TreeView).

Không thực sự muốn đưa ra một chủ đề cũ, nhưng đây là một trong những gần đây nhất tôi đã thấy về chủ đề này và cảm thấy nó sẽ hữu ích cho mọi người biết nó trong thực tế làm việc.

+0

Cảm ơn bạn đã cập nhật, nhưng đối với tôi điều này không hoạt động. Xem câu trả lời của tôi dưới đây. – Rogier

1

Để theo dõi trên Malcom, tôi đã làm cho nó hoạt động bằng cách sử dụng ItemContainerStyle thay vì 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

Nếu bạn đang sử dụng SL5 thì trình định dạng XAML chuẩn sẽ hoạt động. Tuy nhiên, nếu bạn đang sử dụng SL4 hoặc thấp hơn thì bạn sẽ cần phải sử dụng SetterValueBindingHelper từ here. Sau đó, XAML của bạn sẽ trông giống như sau. Hãy chắc chắn rằng bạn cẩn thận sao chép những gì tôi có dưới đây.

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

Cú pháp không chính xác như những gì bạn sẽ sử dụng trong WPF, nhưng nó hoạt động và hoạt động tốt!