Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在treeview中指定数据上下文和绑定分层数据的正确方法是什么?_C#_Wpf_Data Binding_Treeview_Hierarchicaldatatemplate - Fatal编程技术网

C# 在treeview中指定数据上下文和绑定分层数据的正确方法是什么?

C# 在treeview中指定数据上下文和绑定分层数据的正确方法是什么?,c#,wpf,data-binding,treeview,hierarchicaldatatemplate,C#,Wpf,Data Binding,Treeview,Hierarchicaldatatemplate,我有一个相当简单的数据模型: public class ServiceModel { private static readonly IQmiServiceManager ServiceManager = Bootstrap.Instance.DomainManager.QmiServiceManager; private string _serviceName; private ObservableCollection<string> _serviceMe

我有一个相当简单的数据模型:

public class ServiceModel
{
    private static readonly IQmiServiceManager ServiceManager = Bootstrap.Instance.DomainManager.QmiServiceManager;

    private string _serviceName;
    private ObservableCollection<string> _serviceMessages;


    public string Name
    {
        get { return _serviceName; }
        private set { _serviceName = value.ToUpper(); }
    }

    public ObservableCollection<string> Messages
    {
        get { return _serviceMessages; }
        private set { _serviceMessages = value; }
    }


    public ServiceModel(string ServiceName, IList<string> ServiceMessages)
    {
        Name = ServiceName;
        Messages = new ObservableCollection<string>(ServiceMessages);
    }

}
公共类服务模型
{
专用静态只读IQmiServiceManager ServiceManager=Bootstrap.Instance.DomainManager.QmiServiceManager;
私有字符串_serviceName;
私有可观察收集服务消息;
公共字符串名
{
获取{return\u serviceName;}
私有集{u serviceName=value.ToUpper();}
}
公共可观察收集消息
{
获取{return\u serviceMessages;}
私有集{u serviceMessages=value;}
}
公共服务模型(字符串ServiceName,IList ServiceMessages)
{
名称=服务名称;
消息=新的ObservableCollection(ServiceMessages);
}
}
…封装在此视图模型中:

public class ServiceCollectionViewModel
{
    private readonly ObservableCollection<ServiceModel> _serviceModels = new ObservableCollection<ServiceModel>();

    public ObservableCollection<ServiceModel> ServiceModels
    {
        get { return _serviceModels; }
    }

} 
公共类ServiceCollectionViewModel
{
私有只读ObservableCollection _serviceModels=新ObservableCollection();
公共可观测收集服务模型
{
获取{return\u serviceModels;}
}
} 
我有以下treeview xaml定义:

<TreeView Name="ServiceTree" Grid.Row="1" ItemsSource="{Binding Services}">
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
            <Setter Property="FontWeight" Value="Normal" />
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="FontWeight" Value="Bold" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding}">
            <TextBlock Text="{Binding Name}"/>
            <HierarchicalDataTemplate.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Messages}"/>
                </DataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

树中没有输出任何内容。我尝试了以下几个关于分层数据绑定的教程,但我很难理解适合我具体情况的适当技术

另外,应该如何设置数据上下文?我在视图的代码隐藏中设置上下文如下:

public partial class ServiceView : UserControl
{

    private readonly ServiceCollectionViewModel _serviceCollection = new ServiceCollectionViewModel();

    public ObservableCollection<ServiceModel> Services
    {
        get { return _serviceCollection.ServiceModels; }
    }

    public ServiceView()
    {
        InitializeComponent();

        DataContext = _serviceCollection;
        _serviceCollection.LoadServices();

    }
} 
public部分类ServiceView:UserControl
{
私有只读ServiceCollectionViewModel _serviceCollection=new ServiceCollectionViewModel();
公共收集服务
{
获取{return\u servicecolection.ServiceModels;}
}
公共服务视图()
{
初始化组件();
DataContext=\u serviceCollection;
_serviceCollection.LoadServices();
}
} 

你似乎很困惑。您正试图将数据绑定到
ServiceView.Services
属性,那么
ServiceCollectionViewModel
类的作用是什么?视图模型的唯一目的是提供其视图所需的所有数据(和功能)

现在我们可以走不同的路线。。。这完全取决于你真正想要什么。如果要从
UserControl
外部将数据绑定到
ServiceView.Services
属性,则必须将
Services
属性声明为
dependencProperty
。在
UserControl
中,然后使用
相对资源绑定将数据绑定到属性,如下所示:

<TreeView Name="ServiceTree" Grid.Row="1" ItemsSource="{Binding Services}">
    ...
</TreeView>
外部:

<YourPrefix:ServiceView Services="{Binding YourExternalViewModelProperty}" />
综上所述,如果您将
DataContext
设置为对象的实例,那么您的
绑定路径将查看该对象中的属性以解析它们自己。否则,如果在
绑定路径
中设置了
相对资源
(或
元素名称
),则仅更改该
绑定
的数据源,而
绑定路径
应该是这些对象的属性


更新>>>

基本上是对常规的
DataTemplate
类的一个轻微扩展,可以认为是一个带有
ItemsSource
属性的
DataTemplate
。因此,如果可以定义
数据模板的内容
,则可以定义
层次数据模板的内容
。。。只需确保将
HierarchycalDataTemplate.ItemsSource
属性设置为有效的集合属性。。。在您的情况下,
消息
属性:

<TreeView.ItemTemplate>
    <HierarchicalDataTemplate DataType="{x:Type YourPrefix:ServiceModel}" 
        ItemsSource="{Binding Messages}"> <!-- Collection Property In ServiceModel -->
        <TextBlock Text="{Binding Name}" /> <!-- Property In ServiceModel -->
    </HierarchicalDataTemplate>
</TreeView.ItemTemplate>


如果您对
DataTemplate
不太清楚,请查看MSDN上的页面。

这里有许多问题

  • ItemsSource
    绑定应该是到
    ServiceModels
    而不是
    Services
    ,因为这是
    ServiceCollectionViewModel
    中的属性名称。这样你就可以得到顶级的物品

  • 您试图在项目样式内部绑定到
    IsExpanded
    IsSelected
    属性,但视图模型上没有此类属性

  • 在您的
    HierarchycalDataTemplate
    中,您可以将
    ItemsSource
    属性直接绑定到
    TreeViewItem
    DataContext
    ,在本例中,该属性是
    ServiceModel
    。使
    ServiceModel
    实现
    IEnumerable
    公开您的消息,或直接绑定到
    messages
    属性:

  • 第二级
    层次数据模板
    文本
    属性绑定到
    消息
    ,但此级别的
    数据上下文
    字符串
    类型,没有
    消息
    属性。因此,这里您应该绑定到数据上下文本身:

  • 关于数据上下文,最好使用静态资源在XAML中初始化它。此外,定义分层数据模板的更简洁的方法是基于项目类型使用隐式模板。因为您确实不想为更多的层次结构级别(例如:4、5)内联定义层次结构模板。请参见下面完全固定的XAML:

    <Grid>
        <Grid.Resources>
            <!--Data context for the whole Grid-->
            <myNamespace:ServiceCollectionViewModel x:Key="MyViewModel" />
        </Grid.Resources>
        <TreeView Name="ServiceTree"
                  DataContext="{StaticResource MyViewModel}"
                  ItemsSource="{Binding ServiceModels}">
            <TreeView.Resources>
    
                <!--Implicit style for TreeViewItem, IsExpanded and IsSelected have no binding because 
                they are not used by view-models-->
                <Style TargetType="{x:Type TreeViewItem}">
                    <Setter Property="FontWeight" Value="Normal" />
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="FontWeight" Value="Bold" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
    
                <!--Template for the first level items-->
                <HierarchicalDataTemplate DataType="{x:Type myNamespace:ServiceModel}" ItemsSource="{Binding Messages}">
                    <TextBlock Text="{Binding Name}"/>
                </HierarchicalDataTemplate>
    
                <!--Template for the second level, due to the fact that String is not hierarchical
                regular DataTemplate is enough-->
                <DataTemplate DataType="{x:Type system:String}">
                    <TextBlock Text="{Binding}"/>
                </DataTemplate>
    
            </TreeView.Resources>
        </TreeView>
    </Grid>
    
    
    

    <Grid> <Grid.Resources> <!--Data context for the whole Grid--> <myNamespace:ServiceCollectionViewModel x:Key="MyViewModel" /> </Grid.Resources> <TreeView Name="ServiceTree" DataContext="{StaticResource MyViewModel}" ItemsSource="{Binding ServiceModels}"> <TreeView.Resources> <!--Implicit style for TreeViewItem, IsExpanded and IsSelected have no binding because they are not used by view-models--> <Style TargetType="{x:Type TreeViewItem}"> <Setter Property="FontWeight" Value="Normal" /> <Style.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter Property="FontWeight" Value="Bold" /> </Trigger> </Style.Triggers> </Style> <!--Template for the first level items--> <HierarchicalDataTemplate DataType="{x:Type myNamespace:ServiceModel}" ItemsSource="{Binding Messages}"> <TextBlock Text="{Binding Name}"/> </HierarchicalDataTemplate> <!--Template for the second level, due to the fact that String is not hierarchical regular DataTemplate is enough--> <DataTemplate DataType="{x:Type system:String}"> <TextBlock Text="{Binding}"/> </DataTemplate> </TreeView.Resources> </TreeView> </Grid>