简体   繁体   English

如何使用Expression Blend编辑在Visual Studio中创建的DataTemplate?

[英]How can I use Expression Blend to edit a DataTemplate created in Visual Studio?

For those of you using Expression Blend as well as Visual Studio in your real projects, please help me understand how you use Blend and Visual Studio in your everyday development/design tasks , here is a real scenario: 对于那些在实际项目中使用Expression Blend和Visual Studio的人,请帮助我了解如何在日常开发/设计任务中使用Blend和Visual Studio ,这是一个真实的场景:

I created the following simple WPF application in Visual Studio. 我在Visual Studio中创建了以下简单的WPF应用程序。 It shows a list of customer objects with a DataTemplate that shows the customers in simple orange boxes. 显示了一个带有DataTemplate的客户对象列表,该对象以简单的橙色框显示客户。

I now want put some pizazz into this DataTemplate by using Expression Blend. 我现在通过使用Expression Blend 将一些pizazz放入这个DataTemplate中

I open the project in Expression Blend thinking that I'm going to see the orange boxes which I can change the color of, create an animation as I mouse over them, resize it, etc. However, all I see in Expression Blend is a completely blank box . 在Expression Blend中打开这个项目,以为我会看到橙色的盒子,我可以改变它的颜色,在鼠标悬停时创建动画,调整大小等等。但是, 我在Expression Blend中看到的只是一个完全空白的盒子

So I understand: 所以我理解:

  • Expression Blend can't seem to understand that my data is coming from the ViewModel and hence doesn't display it. Expression Blend 似乎无法理解我的数据来自ViewModel ,因此不会显示它。 Is this a limitation of Blend or do I need to change my code in some way so that Blend can interpret what data will be coming out at run-time? 这是Blend的限制还是我需要以某种方式更改我的代码,以便Blend可以解释在运行时会出现什么数据?
  • I'm using Expression Blend 3 which has "sample data" capability. 我正在使用具有“样本数据”功能的Expression Blend 3。 What is the best way to use this sample data feature so that even if it can't interpret the C# and understand what data will be coming out of the ViewModel property to fill the Listbox, how can I get it to at least produce some dummy data so that I can manipulate the DataTemplate? 使用此示例数据功能的最佳方法是什么 ,即使它无法解释C#并了解将从ViewModel属性中填充Listbox的哪些数据,我怎样才能使它至少产生一些虚拟数据,以便我可以操纵DataTemplate?

XAML: XAML:

<Window x:Class="TestStringFormat234.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <DataTemplate x:Key="DataTemplateCustomers">
            <Border CornerRadius="5" Background="Orange" Padding="5" Margin="3">
                <StackPanel Orientation="Horizontal">
                    <TextBlock>
                    <TextBlock.Text>
                        <MultiBinding StringFormat="{}{0} {1} (hired on {2:MMM dd, yyyy})">
                            <Binding Path="FirstName"/>
                            <Binding Path="LastName"/>
                            <Binding Path="HireDate"/>
                        </MultiBinding>
                    </TextBlock.Text>
                    </TextBlock>
                </StackPanel>
            </Border>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ListBox ItemsSource="{Binding GetAllCustomers}"
                 ItemTemplate="{StaticResource DataTemplateCustomers}">
        </ListBox>
    </Grid>
</Window>

Code Behind: 代码背后:

using System.Windows;
using System.Collections.ObjectModel;
using System;

namespace TestStringFormat234
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            DataContext = new CustomerViewModel();
        }
    }

    //view model
    public class CustomerViewModel
    {
        public ObservableCollection<Customer> GetAllCustomers {
            get {
                ObservableCollection<Customer> customers = new ObservableCollection<Customer>();
                customers.Add(new Customer { FirstName = "Jim", LastName = "Smith", HireDate = DateTime.Parse("2007-12-31") });
                customers.Add(new Customer { FirstName = "Jack", LastName = "Jones", HireDate = DateTime.Parse("2005-12-31") });
                return customers;
            }
        }
    }

    //model
    public class Customer
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime HireDate { get; set; }
    }
}

I just figured this out so allow me to answer my own question. 我只是想出来,所以请允许我回答我自己的问题。

I read Laurent's Bugnion enlighting article on this and it turns out I just had to tweak the above code so that I could see the Data from my ViewModel displayed in the Expression Blend GUI and was able to edit the DataTemplate in Blend, save it, and then continued editing in Visual Studio. 我阅读了Laurent的Bugnion文章,并且发现我只需要调整上面的代码,这样我就可以在Expression Blend GUI中看到我的ViewModel中的数据,并且能够在Blend中编辑DataTemplate,保存它,以及然后继续在Visual Studio中编辑。

Basically the changes are: (1) take out the DataContext statement from code behind, (2) add the "local" namespace in XAML, (3) define a local data provider in XAML ("TheDataProvider"), (4) bind to it directly from the ListBox. 基本上改变是:(1)从代码后面取出DataContext语句,(2)在XAML中添加“本地”命名空间,(3)在XAML中定义本地数据提供者(“TheDataProvider”),(4)绑定到它直接来自ListBox。

Here is the code that works in Expression Blend and Visual Studio in full: 以下是完全适用于Expression Blend和Visual Studio的代码:

XAML: XAML:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TestStringFormat234"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Name="window" x:Class="TestStringFormat234.Window1"
    Title="Window1" Height="300" Width="300" mc:Ignorable="d">
    <Window.Resources>
        <local:CustomerViewModel x:Key="TheDataProvider"/>

        <DataTemplate x:Key="DataTemplateCustomers">
            <Border CornerRadius="5" Padding="5" Margin="3">
                <Border.Background>
                    <LinearGradientBrush EndPoint="1.007,0.463" StartPoint="-0.011,0.519">
                        <GradientStop Color="#FFF4EEEE" Offset="0"/>
                        <GradientStop Color="#FFA1B0E2" Offset="1"/>
                    </LinearGradientBrush>
                </Border.Background>
                <StackPanel Orientation="Horizontal">
                    <TextBlock>
                    <TextBlock.Text>
                        <MultiBinding StringFormat="{}{0} {1} (hired on {2:MMM dd, yyyy})">
                            <Binding Path="FirstName"/>
                            <Binding Path="LastName"/>
                            <Binding Path="HireDate"/>
                        </MultiBinding>
                    </TextBlock.Text>
                    </TextBlock>
                </StackPanel>
            </Border>
        </DataTemplate>
    </Window.Resources>
    <Grid >
        <ListBox 
            ItemsSource="{Binding Path=GetAllCustomers, Source={StaticResource TheDataProvider}}"
            ItemTemplate="{StaticResource DataTemplateCustomers}" />
    </Grid>
</Window>

Code Behind: 代码背后:

using System.Windows;
using System.Collections.ObjectModel;
using System;

namespace TestStringFormat234
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
    }

    //view model
    public class CustomerViewModel
    {
        public ObservableCollection<Customer> GetAllCustomers {
            get {
                ObservableCollection<Customer> customers = new ObservableCollection<Customer>();
                customers.Add(new Customer { FirstName = "Jim", LastName = "Smith", HireDate = DateTime.Parse("2007-12-31") });
                customers.Add(new Customer { FirstName = "Jack", LastName = "Jones", HireDate = DateTime.Parse("2005-12-31") });
                return customers;
            }
        }
    }

    //model
    public class Customer
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime HireDate { get; set; }
    }
}

I've got a blog post on this issue: http://www.robfe.com/2009/08/design-time-data-in-expression-blend-3/ 我在这个问题上有一篇博文: http//www.robfe.com/2009/08/design-time-data-in-expression-blend-3/

My post is all about showing data in blend without having to have that data displayed or even created at runtime. 我的帖子是关于在混合中显示数据不必在运行时显示或甚至创建数据。

If one wants to have Blend and Visual Studio see what the datacontext has in design mode only, that can be defined with the debug options on the page. 如果想让Blend和Visual Studio看到datacontext仅在设计模式下具有什么,那么可以使用页面上的调试选项来定义。 Say for example my page (in code-behind) binds its data context to MainVM in my nampespace WP8TestBed, by informing that info on the main page's attributes as d:DataContext, it is only used during design time (I can bind to it using the wizards) and also does not create a new instance of the view model during runtime. 例如,我的页面(在代码隐藏中)将其数据上下文绑定到我的nampespace WP8TestBed中的MainVM,通过将主页的属性信息通知为d:DataContext,它仅在设计时使用(我可以使用它绑定到它)向导)并且在运行时期间也不会创建视图模型的新实例。

Here is the example, all these namespaces are needed(d,mc and the local which is where my ViewModel (MainVM) lives): 下面是示例,需要所有这些命名空间(d,mc和我的ViewModel(MainVM)所在的本地):

<phone:PhoneApplicationPage
x:Class="WP8TestBed.MainPage"
...
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
xmlns:local="clr-namespace:WP8TestBed"
mc:Ignorable="d"
Name="Primary"
d:DataContext="{d:DesignInstance local:MainVM}">

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM