简体   繁体   English

奇怪的行为WPF TreeView ItemContainerStyle和ItemTemplate

[英]Strange Behaviour WPF TreeView ItemContainerStyle and ItemTemplate

I just noticed some strange behaviour of WPF's TreeView. 我只是注意到WPF的TreeView有一些奇怪的行为。 I added both ItemContainerStyle to bind to "IsSelected" of my ViewModel and an ItemsTemplated for custom display of my data. 我添加了ItemContainerStyle绑定到ViewModel的“ IsSelected”,还添加了ItemsTemplated来自定义显示数据。 But now the user cannot change the selected node anymore. 但是现在,用户无法再更改所选节点。 For testing purposes I created a similar UI using ListView and Expander. 为了进行测试,我使用ListView和Expander创建了类似的UI。 This version works as excepted. 此版本例外。 Any tips why TreeView does fail? TreeView失败的任何提示?

 <TreeView ItemsSource="{Binding ElementName=frame, Path=list}">
        <TreeView.ItemContainerStyle>
            <Style TargetType="{x:Type TreeViewItem}" >
                <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
            </Style>
        </TreeView.ItemContainerStyle>
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate>
                <TreeViewItem Header="{Binding}">
                    <TextBlock Text="{Binding Path= Item.SomeData}"/>
                </TreeViewItem>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>

EDIT: My data are not hierachical. 编辑:我的数据不是分层的。 I just want to get the "collapse" feature on displaying a list. 我只想在显示列表时获得“折叠”功能。 Item.SomeData is not a list. Item.SomeData不是列表。 Display of data is as desired. 根据需要显示数据。 Only selection by mouse fails! 仅鼠标选择失败!

alt text http://img682.imageshack.us/img682/3702/bildy.png 替代文字http://img682.imageshack.us/img682/3702/bildy.png

TreeViews work differently. TreeViews的工作方式不同。 The Items inside a HierarchicalDataTemplate are TreeViewItems and any control you specify inside the HierarchicalDataTemplate will function as its Header. HierarchicalDataTemplate内部的项目 TreeViewItems,您在HierarchicalDataTemplate内部指定的任何控件都将用作其标题。 So, basically you are specifying that the Items in your TreeView are TreeViewItems with TreeViewItems as their headers! 因此,基本上,您指定的是TreeView中的Item是TreeViewItems,其中TreeViewItems作为其标题! Instead try this: 而是尝试以下方法:

 <HierarchicalDataTemplate ItemsSource="{Binding Items}"> 
      <Label Content="{Binding}"/>
      <HierarchicalDataTemplate.ItemTemplate>
         <DataTemplate> 
             <TextBlock Text="{Binding Path= Item.SomeData}"/> 
         </DataTemplate>
      </HierarchicalDataTemplate.ItemTemplate> 
  </HierarchicalDataTemplate>

EDIT: I could not reproduce a DataSource that produces the properties you want to bind to, so I wrote some simple code of my own that shows how it all works. 编辑:我无法重现一个数据源,该数据源会生成您想要绑定的属性,因此我编写了一些自己的简单代码来显示其所有工作原理。 Hopefully you will be able to adapt it to your needs: 希望您能够适应您的需求:

<TreeView ItemsSource="{Binding}" Name="Tree">
            <TreeView.ItemContainerStyle>
                <Style TargetType="{x:Type TreeViewItem}" >
                    <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
                </Style>
            </TreeView.ItemContainerStyle>
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Items}">
                    <Label Content="{Binding Name}"/>
                    <HierarchicalDataTemplate.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Path= SomeData}"/>
                        </DataTemplate>
                    </HierarchicalDataTemplate.ItemTemplate>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>

using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;

namespace TreeViewSpike
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            List = new List<ItemList>
                       {
                           new ItemList
                               {
                                   Name = "MyList",
                                   Items = new List<Item> {new Item("1"),
                                                           new Item("2")}
                               },
                           new ItemList
                               {
                                   Name = "MySecondList",
                                   Items = new List<Item> {new Item("3"),
                                                           new Item("4")}
                               }
                       };
            Tree.DataContext = List;
            List[1].IsSelected = true;
        }

        public List<ItemList> List { get; set; }
    }

    public class ItemList: INotifyPropertyChanged
    {
        public string Name{ get; set;}
        private bool _isSelected;
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                _isSelected = value;
                if (PropertyChanged != null)
                    PropertyChanged(this,
                        new PropertyChangedEventArgs("IsSelected"));
                if(_isSelected)
                   MessageBox.Show(Name + " selected");
            }
        }

        public List<Item> Items { get; set; }
        public event PropertyChangedEventHandler PropertyChanged;
    }

    public class Item
    {
        public string SomeData { get; set; }
        public Item(string data)
        {
            SomeData = data;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM