wpf - 为什么这个数据模板在设计时不起作用?

标签 wpf listbox datatemplate design-time

以下简单数据模板仅在运行时有效。在设计时它什么也不显示。为什么会这样?

<DataTemplate x:Key="SomeEnumDataTemplate">
    <ListBox Name="list" Width="20" IsSynchronizedWithCurrentItem="True" SelectedIndex="{Binding Mode=OneWay, Converter={StaticResource EnumToIntConverter}}">
        <ListBox.Template>
            <ControlTemplate TargetType="ListBox">
                <ContentPresenter Content="{TemplateBinding SelectedItem}" />
            </ControlTemplate>
        </ListBox.Template>
        <Rectangle Height="10" Width="10" Fill="Red" />
        <Rectangle Height="10" Width="10" Fill="Green" />
        <Rectangle Height="10" Width="10" Fill="Yellow" />
    </ListBox>
</DataTemplate>

我在另一个 DataTemplate 中像这样使用它:

<HierarchicalDataTemplate x:Key="NodeDataTemplate" ItemsSource="{Binding Children}">
    <StackPanel Orientation="Horizontal" ToolTip="{Binding Description}">            
        <ContentControl ContentTemplate="{StaticResource SomeEnumDataTemplate}" Content="{Binding Mode}" Margin="3,0,0,0" />
        <TextBlock Text="{Binding Name}" />
    </StackPanel>
</HierarchicalDataTemplate>

它再次在具有设计时数据的 UserControl 中使用:

<UserControl x:Class="MyProject.Views.MyView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:ViewModels="clr-namespace:MyProject.ViewModels" mc:Ignorable="d" 
             d:DesignHeight="780" d:DesignWidth="400" d:DataContext="{x:Static ViewModels:SampleData.RootNode}">     
 <TreeView ItemsSource="{Binding}" ItemTemplate="{StaticResource NodeDataTemplate}">
     <TreeView.ItemContainerStyle>
      <Style TargetType="TreeViewItem">
       <Setter Property="IsExpanded" Value="True" />
   </Style>   
  </TreeView.ItemContainerStyle>
 </TreeView>
</UserControl>

最佳答案

您可以轻松创 build 计时数据:

  1. 创建您的数据模型:

    public class Person
    {
        public string Name { get; set; }
    
        public int  Age { get; set; }
    }
    
    public class PersonCollection : List<Person>
    {
        public PersonCollection()
        {
    
        }
    }
    
  2. 创建一个扩展名为 .xaml 的文件,其中包含:

DesignTimeTreeData.xaml

    <local:PersonCollection xmlns:local="clr-namespace:Test_TreeWithDesignData">
        <local:Person Name="Joan Solo" Age="32" />
        <local:Person Name="Amara Skywalker" Age="31" />
    </local:PersonCollection>
  • 使用 d:DataContextd:DesignData 来使用您在 DesignTimeTreeData.xaml 中指定的数据:
  • MainWindow.xaml

        <Window x:Class="Test_TreeWithDesignData.MainWindow"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:local="clr-namespace:Test_TreeWithDesignData"
                Title="MainWindow"
                Height="350"
                Width="525"
                mc:Ignorable="d">
            <Grid>
                <TreeView
                    d:DataContext="{d:DesignData Source=./DesignTimeTreeData.xaml}"
                    ItemsSource="{Binding}">
                    <TreeView.Resources>
                        <DataTemplate DataType="{x:Type local:Person}" >
                            <StackPanel Orientation="Horizontal" Height="25">
                                <Label Content="{Binding Name}"/>
                                <Label Content="{Binding Age}" Margin="3,0,0,0"/>
                            </StackPanel>
                        </DataTemplate>
                    </TreeView.Resources>
                </TreeView>
            </Grid>
        </Window>
    
  • 由于 Window.DataContext 属性通常设置为 ViewModel 并且 TreeView.DataContext 是它的集合,因此,要保持两个数据源都正常工作,您可以用 Grid 包围 TreeView,其中 DataContext 设置为 ViewModel收藏。
  • DummyViewModel.cs

        public class DummyViewModel : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                var handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(propertyName));
                }
            }
    
            public PersonCollection Persons { get; set; }
    
            public DummyViewModel()
            {
                this.Persons = new PersonCollection();
            }
        }
    

    MainWindow.xaml

        <Window x:Class="Test_TreeWithDesignData.MainWindow"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:local="clr-namespace:Test_TreeWithDesignData"
                Title="MainWindow"
                Height="350"
                Width="525"
                mc:Ignorable="d">
            <Window.DataContext>
                <local:DummyViewModel />
            </Window.DataContext>
    
            <Grid Name="RootGrid">
                <Grid Name="TreeGrid" DataContext="{Binding Persons}">
                    <TreeView d:DataContext="{d:DesignData Source=./DesignTimeTreeData.xaml}"
                        ItemsSource="{Binding}">
                        <TreeView.Resources>
                            <DataTemplate DataType="{x:Type local:Person}" >
                                <StackPanel Orientation="Horizontal" Height="25">
                                    <Label Content="{Binding Name}"/>
                                    <Label Content="{Binding Age}" Margin="3,0,0,0"/>
                                </StackPanel>
                            </DataTemplate>
                        </TreeView.Resources>
                    </TreeView>
                </Grid>
            </Grid>
        </Window>
    

    结果:

    enter image description here

    编辑

    下一个问题是:如何在设计器中展开项目?

  • Person 将拥有一个人员集合:

    public class Person
    {
        public string Name { get; set; }
    
        public int  Age { get; set; }
    
        public PersonCollection Childs { get; set; }
    }
    
  • 设计时数据将有一个子数据

  • DesignTimeTreeData.xaml

        <local:PersonCollection xmlns:local="clr-namespace:Test_TreeWithDesignData">
            <local:Person Name="Joan Solo" Age="32" />
            <local:Person Name="Amara Skywalker" Age="31">
                <local:Person.Childs>
                    <local:PersonCollection>
                        <local:Person Name="Han Skywalker" Age="10" />
                    </local:PersonCollection>
                </local:Person.Childs>
            </local:Person>
        </local:PersonCollection>
    
  • 树现在将有一个 HierarchicalDataTemplate:

    <HierarchicalDataTemplate
        DataType="{x:Type local:Person}"
        ItemsSource="{Binding Childs}">
        <StackPanel Orientation="Horizontal" Height="25">
            <Label Content="{Binding Name}"/>
            <Label Content="{Binding Age}" Margin="3,0,0,0"/>
        </StackPanel>
    </HierarchicalDataTemplate>
    
  • 并且 TreeView 将绑定(bind)到 DesignerProperties.IsInDesignMode 以展开设计器中的项目:

    <TreeView.ItemContainerStyle>
        <Style TargetType="TreeViewItem">
            <Style.Triggers>
                <DataTrigger
                        Binding="{Binding RelativeSource={RelativeSource Self}, Path=(pf:DesignerProperties.IsInDesignMode)}"
                        Value="true"
                        >
                    <Setter Property="IsExpanded" Value="True" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TreeView.ItemContainerStyle>
    
  • 这是窗口的 xaml:

    MainWindow.xaml

        <Window x:Class="Test_TreeWithDesignData.MainWindow"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:local="clr-namespace:Test_TreeWithDesignData"
                xmlns:pf="clr-namespace:System.ComponentModel;assembly=PresentationFramework"
                Title="MainWindow"
                Height="250"
                Width="325"
                mc:Ignorable="d"
                >
            <Window.DataContext>
                <local:DummyViewModel />
            </Window.DataContext>
    
            <Grid Name="RootGrid">
    
                <Grid Name="TreeGrid" DataContext="{Binding Persons}">
                    <TreeView
                        d:DataContext="{d:DesignData Source=./DesignTimeTreeData.xaml}"
                        ItemsSource="{Binding}"
                        >
                        <TreeView.ItemContainerStyle>
                            <Style TargetType="TreeViewItem">
                                <Style.Triggers>
                                    <DataTrigger
                                            Binding="{Binding RelativeSource={RelativeSource Self}, Path=(pf:DesignerProperties.IsInDesignMode)}"
                                            Value="true"
                                            >
                                        <Setter Property="IsExpanded" Value="True" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </TreeView.ItemContainerStyle>
                        <TreeView.Resources>
                            <HierarchicalDataTemplate
                                DataType="{x:Type local:Person}"
                                ItemsSource="{Binding Childs}"
                                >
                                <StackPanel Orientation="Horizontal" Height="25">
                                    <Label Content="{Binding Name}"/>
                                    <Label Content="{Binding Age}" Margin="3,0,0,0"/>
                                </StackPanel>
                            </HierarchicalDataTemplate>
                        </TreeView.Resources>
                    </TreeView>
                </Grid>
            </Grid>
        </Window>
    

    这就是结果:

    enter image description here

    关于wpf - 为什么这个数据模板在设计时不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4224332/

    相关文章:

    c# - 登录应用程序

    c# - WPF 工具包 DataGrid 显示字段,即使可浏览属性设置为 false

    c# - 枢轴页面部分的垂直滚动

    wpf - 慢速组合框性能

    wpf - 如何绑定(bind)到字典中的项目?

    c# - 以编程方式更改列表框项目背景颜色

    wpf - WPF MDI 应用程序中的组合根在哪里?

    vb.net - CheckedListBox 项目到 TextBox

    c# - 使用 lb_addstring 添加到 C# 列表框的项目不会影响 items.count

    wpf - 在 WPF 中访问 DataTemplate 中的项目