WPF在具有接口集合的设计器中显示伪数据

时间:2014-06-22 08:57:56

标签: c# wpf interface designer

我希望在Visual Studio Designer中显示虚假数据。我使用View Service Interface方式来实现这个时效(这是最小的例子):

-ServiceView
  -IMainWindow.cs
  -ICustomer.cs
-SampleData
  -MainWindowDesign.cs
  -CustomerDesign.cs
  -Data.xaml

IMainWindow.cs

namespace TestDesignSampleData.ServiceView
{
    interface IMainWindow
    {
        ObservableCollection<ICustomer> Customers { get; }
    }
}

ICustomer.cs

namespace TestDesignSampleData.ServiceView
{
    interface ICustomer
    {
        string Name { get; set; }
    }
}

MainWindowDesign.cs

namespace TestDesignSampleData.SampleData
{
    class MainWindowDesign : IMainWindow
    {
        public ObservableCollection<ICustomer> Customers { get; set; }

        public MainWindowDesign()
        {
        //Customers = new ObservableCollection<ICustomer>();
        }
    }
}

CustomerDesign.cs

namespace TestDesignSampleData.SampleData
{
    class CustomerDesign : ICustomer
    {
        public string Name { get; set; }
    }
}

Data.xaml

<sd:MainWindowDesign xmlns:sd="clr-namespace:TestDesignSampleData.SampleData">
    <sd:MainWindowDesign.Customers>
        <sd:CustomerDesign Name="Charly Sparow"/>
        <sd:CustomerDesign Name="Jacky Chan"/>
        <sd:CustomerDesign Name="Dora Exploring"/>
    </sd:MainWindowDesign.Customers>
</sd:MainWindowDesign>

这可以构建和执行,但数据不会显示,设计人员会在Data.xaml中为集合的每一行发送此错误:

Error 1 The specified value cannot be assigned to the collection. 
The following type was expected: "ICustomer".

出于某种原因,客户设计不被视为ICustomer。

编辑: 我认为这是Visual Studio设计师的bug。我没有混合这个问题。也许Blend设计师的编译器更先进。

重现错误的最小项目:

https://github.com/Orwel/DesignerError/releases/tag/CompiledProject

2 个答案:

答案 0 :(得分:2)

我认为XAML设计师在解释具有接口类型的数组/集合时存在一些问题。如果接口不是必需的,则可以使用继承。 定义您的ICustomer - &gt;创建基类Customer实现ICustomer,然后通过继承Customer而不是ICustomer来创建特殊类。

由于您将拥有基类,您可以创建Customers的数组/集合,而不是在Visual Studio中与XAML设计器一起正常工作的ICustomer。

答案 1 :(得分:0)

我无法确定您是否/何时/如何绑定到您的MainWindowDesign类,但我很幸运使用以下结构(为您的示例自定义)以在WPF中显示设计时数据。 / p>

public class MainWindowDesignFactory
{
    public static IMainWindow ViewModel
    {
        get
        {
            return new MainWindowDesignFactory().Create();
        }
    }

    public IMainWindow Create()
    {
        var vm = new MainWindowDesign();

        vm.Customers = new ObservableCollection<ICustomer>()
        {
            new CustomerDesign() { Name = "Charly Sparow" },
            new CustomerDesign() { Name = "Jacky Chan" },
            new CustomerDesign() { Name = "Dora Exploring" }
        };

        return vm;
    }

    private class MainWindowDesign : IMainWindow
    {
        public ObservableCollection<ICustomer> Customers { get; set; }
    }

    private class CustomerDesign : ICustomer
    {
        public string Name { get; set; }
    }
}

然后在XAML文件中:

<Window 
    x:Class="DesignTimeDataExample.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:TestDesignSampleData_SampleData="clr-namespace:TestDesignSampleData.SampleData"
    Title="MainWindow" 
    Height="350" 
    Width="525"
    d:DataContext="{x:Static TestDesignSampleData_SampleData:MainWindowDesignFactory.ViewModel}">
    <Grid>
        <ListBox ItemsSource="{Binding Customers}" />
    </Grid>
</Window>

这里的重要元素是XAML中的d:DataContext属性(它完全符合您的预期,在设计器中设置DataContext)和实际的MainWindowDesignFactory类,它具有静态ViewModel属性绑定到。

还有其他方法,包括使用:

d:DataContext="{d:DesignInstance Type={x:Type TestDesignSampleData_SampleData:MainWindowDesign}, IsDesignTimeCreatable=True}"

但是我对Factory / Static属性组合有了更多好运(使用DesignInstance属性创建实例的设计时间有点不稳定,使用手动创建的Factory给了我更多控制和更少的设计师错误)。

上面的代码有点粗糙,但应该给你一个起点。