代码之家  ›  专栏  ›  技术社区  ›  Ristogod

WPF/XAML树视图在绑定后不突出显示节点

  •  3
  • Ristogod  · 技术社区  · 15 年前

    所以我对TreeView有意见。如果我静态地构建一个树视图,那么树中的每个节点都是可选择的,因为当我单击它时,它会将自身突出显示为蓝色,表示该节点已被选中。

    <TreeView 
        Grid.Column="0"
        Grid.Row="2"
        MinHeight="100" 
        MinWidth="100"
        BorderBrush="White"
        DataContext="{Binding Projects, Source={x:Static SizingApp:Manager.Instance}}">
    <TreeViewItem Header="Project 1" IsExpanded="True">
        <TreeViewItem Header="Step 1" IsExpanded="True">
            <TreeViewItem Header="Load 1" IsExpanded="True"></TreeViewItem>
            <TreeViewItem Header="Load 2" IsExpanded="True"></TreeViewItem>
        </TreeViewItem>
        <TreeViewItem Header="Step 2" IsExpanded="True">
            <TreeViewItem Header="Load 1" IsExpanded="True"></TreeViewItem>
            <TreeViewItem Header="Load 2" IsExpanded="True"></TreeViewItem>
        </TreeViewItem>
    </TreeViewItem>
    

    但是,我绑定到TreeView来填充它。此外,我绑定到实现 Emiel Jongerius's BindableObjectBase3 class . 这是一个非常好的基类实现,它允许我的对象可绑定,并实现inotifyPropertyChanged接口,同时考虑手动DependencyProperty管理。

    这是我试图在TreeView中实现的基本类结构(从实际对象中简化)。

        public abstract class MyCustomClass : BindableObjectBase3
    {
        private string m_strName;
    
        public virtual string Name
        {
            get
            {
                using (this.GetPropertyTracker(() => this.Name))
                {
                    return m_strName;
                }
            }
            set
            {
                this.SetValue(ref this.m_strName, value, () => this.Name);
            }
        }
    }
    
    public class Project : MyCustomClass
    {
        private List<Step> m_steps;
    
        public List<Step> Steps
        {
            get
            {
                using (this.GetPropertyTracker(() => this.Steps))
                {
                    return m_steps;
                }
            }
            set
            {
                this.SetValue(ref this.m_steps, value, () => this.Steps);
            }
        }
    }
    
    public class Step : MyCustomClass
    {
        private List<Load> m_loads;
    
        public List<Load> Loads
        {
            get
            {
                using (this.GetPropertyTracker(() => this.Loads))
                {
                    return m_loads;
                }
            }
            set
            {
                this.SetValue(ref this.m_loads, value, () => this.Steps);
            }
        }
    }
    
    public class Load : MyCustomClass
    {
    }
    

    这是我用来实现树视图的基本XAML:

    <TreeView 
        Grid.Column="0"
        Grid.Row="2"
        MinHeight="100" 
        MinWidth="100"
        BorderBrush="White"
        DataContext="{Binding Projects, Source={x:Static SizingApp:Manager.Instance}}">
        <TreeView.Resources>
            <HierarchicalDataTemplate x:Key="LoadTemplate">
                <TreeViewItem Header="{Binding Path=Name}">
                </TreeViewItem>
            </HierarchicalDataTemplate>
            <HierarchicalDataTemplate x:Key="StepTemplate">
                <TreeViewItem Header="{Binding Path=Name}" IsExpanded="True"
                        ItemsSource="{Binding Path=Loads}"
                        ItemTemplate="{StaticResource LoadTemplate}">
                </TreeViewItem>
            </HierarchicalDataTemplate>
            <HierarchicalDataTemplate x:Key="ProjectTemplate">
                <TreeViewItem Header="{Binding Path=Name}" IsExpanded="True"
                        ItemsSource="{Binding Path=Steps}"
                        ItemTemplate="{StaticResource StepTemplate}">
                </TreeViewItem>
            </HierarchicalDataTemplate>
        </TreeView.Resources>
        <TreeViewItem 
                Header="{Resx ResxName=PSSPECApplication.Controls.ProjectControlResources, Key=projectTree_Header}"
                ItemsSource="{Binding}"
                IsExpanded="True"
                Focusable="True"
                ItemTemplate="{StaticResource ProjectTemplate}">
        </TreeViewItem>
    </TreeView>
    

    现在,所有这些工作都很好,就绑定而言。我可以绑定到一个ObservableCollection<Project>,当我添加/删除/操作项目时,TreeView会相应地更新。

    但是,TreeView中唯一似乎可以选择的节点是第一个节点(静态节点)。通过动态绑定创建的所有其他节点并不表示它们在GUI上被选中。我希望它们在单击时也会突出显示蓝色。但是他们什么也不做。有人知道为什么吗?

    2 回复  |  直到 15 年前
        1
  •  4
  •   John Bowen    15 年前

    不应在项模板中显式定义TreeView项。无法选择任何项的原因是它们没有父树视图来控制选择行为。您需要让TreeView为您生成TreeView项控件,并且只使用项模板来定义头的UI及其项的绑定。用这样的方法代替:

    <Window.Resources>
        <HierarchicalDataTemplate x:Key="LoadTemplate">
            <TextBlock Text="{Binding Path=Name}"/>
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate x:Key="StepTemplate" ItemsSource="{Binding Loads}" ItemTemplate="{StaticResource LoadTemplate}">
            <TextBlock Text="{Binding Path=Name}"/>
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate x:Key="ProjectTemplate" ItemsSource="{Binding Steps}" ItemTemplate="{StaticResource StepTemplate}">
            <TextBlock Text="{Binding Path=Name}"/>
        </HierarchicalDataTemplate>
    </Window.Resources>
    
    <TreeView MinHeight="100" MinWidth="100" BorderBrush="White"
              ItemsSource="{Binding Path=Projects}"
              ItemTemplate="{StaticResource ProjectTemplate}">
        <TreeView.ItemContainerStyle>
            <Style TargetType="{x:Type TreeViewItem}">
                <Setter Property="IsExpanded" Value="True" />
            </Style>
        </TreeView.ItemContainerStyle>
    </TreeView>
    
        2
  •  1
  •   Adam Davis    15 年前

    我的树视图就像原来的海报描述的那样。我可以选择TreeView控件中的所有内容,但是如果选择子节点,那么父节点就是突出显示的内容,即使它绑定并单击了子节点。我试图将代码构造成类似于JohnBowen的建议,但仍然得到相同的结果。这是我的XAML代码:

       <Fluent:RibbonWindow.Resources>
            <HierarchicalDataTemplate x:Key="MyTreeViewStyle" ItemsSource="{Binding Contacts}">
                <!-- Display the Index by showing it's Index string -->
                <StackPanel Orientation="Horizontal">
                    <Image x:Name="img" Width="16" Height="16" Stretch="Fill" Source="Images\closedfolder16.png" />
                    <TextBlock Text="{Binding Index}" Margin="5,0" ToolTip="{Binding Index}"/>
                </StackPanel>
                <HierarchicalDataTemplate.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <Image x:Name="img2" Width="16" Height="16" Stretch="Fill" Source="Images\closedfolder16.png" />
                            <TextBlock Text="{Binding Name}" Margin="5,0" ToolTip="{Binding Name}"/>
                        </StackPanel>
                    </DataTemplate>
                </HierarchicalDataTemplate.ItemTemplate>
            </HierarchicalDataTemplate>
    </Fluent:RibbonWindow.Resources>
    

    然后我在TreeView控件中使用它:

                    <Grid>
                        <TreeView Margin="2,2,2,2" x:Name="MyTreeView" ItemTemplate="{StaticResource MyTreeViewStyle}" ItemContainerStyle="{StaticResource AlwaysExpand}" ScrollViewer.CanContentScroll="True" BorderThickness="0" TreeViewItem.Selected="btnDisplayContact_Click" />                       
                    </Grid>
    

    结果是这个屏幕截图,注意单击子节点后父节点d如何突出显示,而不是子节点如何突出显示:

    http://home.swbell.net/davis32/Snapshot.png

    无法发布图像,因此只需剪切并粘贴URL链接。