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

8
对于那些在实际项目中同时使用Expression Blend和Visual Studio的人,请帮助我了解你们如何在日常开发/设计任务中使用Blend和Visual Studio。以下是一个真实场景:
我在Visual Studio中创建了以下简单的WPF应用程序。它显示了一个客户对象列表,其中使用DataTemplate将客户显示在简单的橙色框中。
现在,我想在这个DataTemplate中加入一些华丽效果,使用Expression Blend进行编辑。
我打开Expression Blend中的项目,希望看到可以更改颜色、创建动画及调整大小等功能的橙色框。然而,我在Expression Blend中看到的是完全空白的框。
所以我理解如下:
- Expression Blend似乎无法理解我的数据来自ViewModel,因此不会显示它。这是Blend的限制还是我需要以某种方式更改代码,使Blend能够解释运行时将输出哪些数据? - 我正在使用具有“示例数据”功能的Expression Blend 3。最佳的使用示例数据功能的方法是什么?即使它不能解释C#并理解将从ViewModel属性中输出哪些数据来填充Listbox,我该如何获得一些虚拟数据,以便我可以操作DataTemplate?
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>

代码后台:

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

2
为什么不将您的答案作为答案并自行接受呢?这样别人就可以更容易地查看了。 - Johnno Nolan
我会尽量去做,但是有时候时间限制让这变得更困难:你必须在回答自己的问题之前等待48个答案, 然后再等待48小时才能接受自己的答案。 - Edward Tanguay
至少答案中有这个。 - Johnno Nolan
3个回答

7
我刚刚弄明白了,所以让我回答自己的问题。
我阅读了Laurent's Bugnion enlighting article on this,发现我只需要调整上面的代码,就可以在Expression Blend GUI中看到来自我的ViewModel的数据,并能够编辑Blend中的DataTemplate,保存后继续在Visual Studio中编辑。
基本上更改如下:(1)从代码中删除DataContext语句,(2)在XAML中添加“local”命名空间,(3)在XAML中定义本地数据提供程序(“TheDataProvider”),(4)直接从ListBox绑定到它。
以下是在Expression Blend和Visual Studio中完全可用的代码:
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>

代码后端:

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

谢谢Edward,我曾经遇到过类似的问题——尝试在数据模板中公开我的主窗口视图模型,而这个解决方案完美地解决了它。向你自己和Laurent致敬,如果他看到这篇文章的话 :) - si618

2

0

如果想让Blend和Visual Studio仅在设计模式下查看数据上下文中的内容,可以在页面的调试选项中定义。例如,我的页面(在代码后台)将其数据上下文绑定到WP8TestBed命名空间中的MainVM,通过在主页面属性中通知该信息作为d:DataContext,在设计时仅使用它(我可以使用向导将其绑定),并且在运行时不会创建视图模型的新实例。

这是一个示例,需要所有这些命名空间(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}">

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接