【问题标题】:WPF/XAML TreeView doesn't Hightlight Nodes after Binding绑定后 WPF/XAML TreeView 不突出显示节点
【发布时间】:2010-08-24 14:54:50
【问题描述】:

所以我遇到了 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
{
}

这是我用来实现 TreeView 的基本 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 并且当我添加/删除/操作项目时,TreeView 会相应地更新。

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

【问题讨论】:

  • 我不敢相信以前没有人遇到过这个问题?

标签: wpf xaml treeview binding


【解决方案1】:

您不应该在您的 ItemTemplates 中明确定义 TreeViewItems。您无法选择任何项目的原因是它们没有父 TreeView 来控制选择行为。您需要让 TreeView 为您生成 TreeViewItem 控件,并且只使用项目模板来定义标题的 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】:

我的 TreeView 的行为与原始海报描述的一样。我可以选择我的 TreeView 控件中的所有内容,但是如果我选择一个子节点,即使它绑定并单击子节点,父节点也是突出显示的。我尝试将我的代码结构化为类似于 John Bowen 的建议,但仍然得到相同的结果。这是我的 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 链接即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-14
    • 1970-01-01
    • 2011-05-11
    • 1970-01-01
    • 2012-05-13
    • 2021-11-30
    • 1970-01-01
    相关资源
    最近更新 更多