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

发布于 2024-10-03 12:15:31 字数 2191 浏览 7 评论 0 原文

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

<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>

The following simple datatemplate only works at runtime. At designtime it displays nothing. Why is this so?

<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>

I use it like this in another 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>

Which again is used in a UserControl that has design-time data:

<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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

鸢与 2024-10-10 12:15:31

您可以轻松创建设计时数据:

  1. 创建您的数据模型:

    公共类 Person
    {
        公共字符串名称{获取;放; }
    
        公共 int 年龄 { 得到;放; }
    }
    
    公共类 PersonCollection : List
    {
        公共 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>
  1. 使用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>
  1. 由于 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>

结果:

在此处输入图像描述

编辑

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

  1. Person 将拥有一个人的集合:

    公共类 Person
    {
        公共字符串名称{获取;放; }
    
        公共 int 年龄 { 得到;放; }
    
        公共 PersonCollection Childs { 获取;放; }
    }
    
  2. 设计时数据将有一个子级

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>
  1. 树现在将有一个 HierarchicalDataTemplate:

    <前><代码><分层数据模板
    DataType =“{x:本地类型:人员}”
    ItemsSource="{绑定子项}">

    <标签内容=“{绑定名称}”/>
    <标签内容=“{绑定年龄}”边距=“3,0,0,0”/>


  2. 并且 TreeView 将绑定到 DesignerProperties.IsInDesignMode 以展开中的项目设计师:

    ;
        <样式TargetType =“TreeViewItem”>
            <样式.触发器>
                <数据触发
                        Binding =“{绑定RelativeSource = {RelativeSource Self},Path =(pf:DesignerProperties.IsInDesignMode)}”
                        值=“真”
                        >
                    
                
            
        
    
    

这是窗口的 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>

这是结果:

在此处输入图像描述

You can easily create design time data:

  1. Create your DataModel:

    public class Person
    {
        public string Name { get; set; }
    
        public int  Age { get; set; }
    }
    
    public class PersonCollection : List<Person>
    {
        public PersonCollection()
        {
    
        }
    }
    
  2. Create a file with .xaml extension containing:

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>
  1. Use the d:DataContext and d:DesignData to use the data you specified in the 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>
  1. Since tipically the Window.DataContext property is set to a ViewModel and the TreeView.DataContext is a collection of it, in order yo keep both datasources working, you can surround the TreeView with a Grid which DataContext is set to the ViewModel's collection.

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>

Result:

enter image description here

Edit

The next question is going to be: Ho do I expand the items in the Designer?

  1. The Person is going to have a collection of persons:

    public class Person
    {
        public string Name { get; set; }
    
        public int  Age { get; set; }
    
        public PersonCollection Childs { get; set; }
    }
    
  2. The design time data is going to have a child

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>
  1. The tree is going to have a HierarchicalDataTemplate now:

    <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>
    
  2. And the TreeView will bind to the DesignerProperties.IsInDesignMode to expand the items in the designer:

    <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>
    

This is the xaml for the window:

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>

And this is the result:

enter image description here

口干舌燥 2024-10-10 12:15:31

一旦你开始 Binding,设置 DataContext、ItemSource 等,设计器就会对你大发雷霆。只需删除所有绑定(看起来像 3 个),您的设计器就可以工作了。将其全部排列好,或者执行任何您需要执行的操作,然后重新添加绑定。

Once you start Binding, setting DataContext, ItemSource etc, the designer will crap out on you. just remove all your bindings (looks like 3) and your designer will work. Get it all lined up, or whatever you need to do, then add bindings back.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文