如何访问正确的datacontext

时间:2015-03-23 15:33:09

标签: c# wpf

我正在使用HierarchicalDataTemplates构建一个树视图,并希望有一些节点被扩展。节点有一个属性" IsNodeExpanded"我希望将属性IsExpanded绑定到。

遇到麻烦的地方是绑定到这个属性。例如。此

<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
    <Setter Property="IsExpanded"
            Value="{Binding DataContext.IsNodeExpanded, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}">
    </Setter>
</Style>

将绑定到我的MainViewModel上定义的属性IsNodeExpanded

<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
    <Setter Property="IsExpanded"
            Value="{Binding IsNodeExpanded}">
    </Setter>
</Style>

根本不起作用,因为我猜,绑定有一个datacontext问题。

如何引用正确的datacontext?

为了完整性,这是我的TreeView

 <TreeView ItemsSource="{Binding _questions}">
 <TreeView.Resources>
     <HierarchicalDataTemplate DataType="{x:Type local:Question}"
                               ItemsSource="{Binding Converter={StaticResource QuestionConverter}}">
         <StackPanel Orientation="Horizontal">
             <TextBlock Text="{Binding Path=Name}" />
         </StackPanel>
     </HierarchicalDataTemplate>
     <HierarchicalDataTemplate DataType="{x:Type local:MainOption}"
                               ItemsSource="{Binding MainOptions}">
         <StackPanel Orientation="Horizontal">
             <CheckBox Content="{Binding Path=Name}"
                       IsChecked="{Binding Path=IsSelected}"
                       Command="{Binding DataContext.ToggleSelectedMetaItem, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
                       CommandParameter="{Binding Path=MetaItemId}" />
         </StackPanel>
     </HierarchicalDataTemplate>

 </TreeView.Resources>
 <TreeView.ItemContainerStyle>
     <Style TargetType="{x:Type TreeViewItem}">
         <Setter Property="IsExpanded"
                 Value="{Binding DataContext.IsNodeExpanded, RelativeSource={RelativeSource FindAncestor, AncestorType=TreeView}}">
         </Setter>
     </Style>
 </TreeView.ItemContainerStyle>

修改

public class MainOption
{
    public string Name { get; set; }
    public int MetaItemId { get; set; }
    public bool IsSelected { get; set; }

    public MainOption()
    {
        this.IsSelected = true;
    }
}

public class Question
{
    public string Name { get; set; }
    public List<MainOption> MainOptions { get; set; }

    public Question()
    {
        MainOptions = new List<MainOption>();
    }
}

1 个答案:

答案 0 :(得分:1)

在ItemContainerStyle中,绑定到IsNodeExpanded属性时不应定义相对源。如果itemssource _questions是问题列表,则{Binding IsNodeExpanded}绑定到IsNodeExpanded类的Question属性。我觉得你错过了这个属性。

这是xaml:

<TreeView ItemsSource="{Binding Questions}">
    <TreeView.Resources>
        <DataTemplate x:Key="OptionTemplate" DataType="l:MainOption">
            <CheckBox IsChecked="{Binding IsSelected}" Content="{Binding Name}" />
        </DataTemplate>
    </TreeView.Resources>
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate DataType="l:Question" ItemsSource="{Binding MainOptions}"
                                ItemTemplate="{StaticResource OptionTemplate}" ItemContainerStyle="{x:Null}">
            <!-- DataContext of type Question -->
            <TextBlock Text="{Binding Name}" />
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
    <TreeView.ItemContainerStyle>
        <Style TargetType="TreeViewItem">
            <Setter Property="IsExpanded" Value="{Binding IsNodeExpanded}" />
        </Style>
    </TreeView.ItemContainerStyle>

</TreeView>

和C#代码:

public class MainWindowViewModel : BindableBase
{
    public MainWindowViewModel()
    {
        Questions = Enumerable.Range(1, 10)
            .Select(i => new Question
            {
                Name = "Question " + i,
                MainOptions = Enumerable.Range(1, 5)
                    .Select(j => new MainOption {Name = "Option " + i})
                    .ToList()
            })
            .ToList();
    }

    public List<Question> Questions { get; private set; }
}

public class Question
{
    public string Name { get; set; }
    public List<MainOption> MainOptions { get; set; }
    public bool IsNodeExpanded { get; set; }

    public Question()
    {
        IsNodeExpanded = true;
        MainOptions = new List<MainOption>();
    }
}

重点是,您在threeview中设置了根项的Style和ItemTemplate。在HierarchicalItemTemplate中,ItemSource用于生成子项,ItemContaierStyle用于影响子项的样式,而ItemTemplate用于影响子项的datatempalte