2009-11-27 69 views
4

如何在设计时从我的WPF应用程序获取应用程序的目录?我需要在设计时访问应用程序当前目录中的资源,而我的XAML正在设计器中显示。我无法使用this question中指定的解决方案,因为在设计时System.IO.Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)System.Reflection.Assembly.GetExecutingAssembly().Location指向IDE的位置(Visual Studio ... Common7或其他)。如何在设计时从我的WPF应用程序获取应用程序的目录?

根据要求进一步澄清我的目标:我想在设计时访问数据库表并显示该数据的图形。这个设计是在Visual Studio 2008中完成的,所以我需要的是一个针对特定问题的非常具体的解决方案,那就是获取我的应用程序的程序集目录。

+0

你是指可执行文件的路径吗? – Pieter888 2009-11-27 13:47:38

+0

是的,没错。 – luvieere 2009-11-27 13:57:33

回答

5

从您的描述中可以看出,您的代码实际上是在Visual Studio中的WPF设计器内部运行的,例如它是用于设计的自定义控件库的一部分。

在这种情况下,Assembly.GetEntryAssembly()返回NULL,但下面的代码获取的路径,应用程序目录:

string applicationDirectory = (
    from assembly in AppDomain.CurrentDomain.GetAssemblies() 
    where assembly.CodeBase.EndsWith(".exe") 
    select System.IO.Path.GetDirectoryName(assembly.CodeBase.Replace("file:///", "")) 
    ).FirstOrDefault(); 

下面的步骤可以用来证明这个作品里面VS.NET 08年的WPF设计工具:

  1. 将此代码为“WPF自定义控件库”或“类库”项目
  2. 添加任何代码要读取数据库并显示返回里面的数据(以我来说,我只是返回的应用程序目录本身作为一个字符串)
  3. 参考从项目库中的项目,你正在设计
  4. 使用自定义控件或类从一个XAML文件来填充您的DataContext或以其他方式提供数据给你的用户界面(在我的情况下,我使用x:Static绑定DataContext)
  5. 使用“Windows Presentation Foundation Designer”编辑该XAML文件,只需双击即可,除非您更改了默认编辑器,在这种情况下,请使用“打开...“

当您按照以下步骤操作时,您正在查看的对象将被填充wi在运行时和设计时都可以使用数据库中的数据。

还有其他情况下,同样的技术也可以正常工作,并且根据您的需要还有其他解决方案可用。请让我们知道您的需求是否与我上面假设的不同。例如,如果你正在编写一个VS.NET加载项,那么你就完全不同了。

+0

谢谢你让我从痛苦中解脱出来。 – Grokodile 2011-10-14 19:46:28

+2

在Visual Studio 2010之后不再有效。 – 2014-04-13 23:47:14

+0

- 将从AppDomain.CurrentDomain.GetAssemblies()返回多个可执行文件(.exe文件),第一个通常是:'%ProgramFiles%\ Microsoft Visual Studio \ Common7 \ IDE \ XDesProc.exe' - Visual Studio创建一个设计时应用程序域和* shadow拷贝*加载程序集。所以你的exe的路径(从'GetAssemblies()'返回的那个你可以从它的名字中识别出来的路径)就是这样的:':\ Users \ \ AppData \ Local \ Microsoft \ VisualStudio \ \ Designer \ ShadowCache \ \ \ YourExecutable.exe' – 2014-04-13 23:57:29

0

我不认为这是可能的 - 你要求的可能还没有建立的装配的位置。您的设计时代码不会在您的应用程序中运行,而必须对IDE做出一些假设。这种感觉对我来说是错误和脆弱的 - 考虑以下问题:

  • 项目是否已建成?
  • 如果没有,那么没有可执行文件来获取路径,那么呢?
  • 其他文件是否存在,如果它尚未建立,或者他们构建的文物?
  • 如果它已经建成,它建在哪里?
  • 你需要考虑其他IDE吗?

在这种情况下,您应该要求用户在设计时提供或浏览路径,方法是在对象上添加一个属性供他们编辑。您的设计时间代码然后可以使用该属性的值来查找它需要的值。

+0

“关于IDE的假设”?什么假设?它是Visual Studio,并且如果构建配置文件是Release,并且需要到我的调试文件夹,则需要我的项目Release文件夹的路径。 – luvieere 2009-11-27 13:59:59

+0

我的意思是你需要知道它在什么地方输出组件。也许你可以告诉我们更多关于你为什么要这样做的原因;也许这个问题有一个更简单的解决方案? – GraemeF 2009-11-27 15:18:11

+0

没有更简单的解决方案:我想在设计时访问数据库表并显示该数据的图形。这个设计是在Visual Studio 2008中完成的,所以我需要的是针对一个非常具体的问题的非常具体的解决方案。 – luvieere 2009-11-27 20:24:32

0

您是否试图支持设计师(如视觉工作室设计师或Blend)?

如果是这样,那么有各种不同的方法来解决这个问题。您通常不希望依赖可执行文件的相对路径,因为它可以用各种不同的设计工具(VS,Expression Blend等)来托管。

也许您可以更全面地解释您尝试解决的问题我们可以提供更好的答案?

-2

好的,鉴于这里的进一步澄清是我会做的。

与GraemeF提出的问题保持一致,做你想做的事情是脆弱的,并且最好是打破。

因此,一般的做法是将设计时间数据支持视为完全不同的方法,然后运行时数据支持。很简单,你在你的设计时间环境和这个数据库之间创建的耦合是一个坏主意。

为了简单地提供可视化的设计时间数据,我更愿意使用遵循通用接口作为运行时类的模拟类。这给了我一种显示数据的方式,我可以确保它是正确的类型,并符合与运行时对象相同的合同。然而,这是一个完全不同的类,用于设计时支持(并且经常用于单元测试)。

举例来说。如果我有需要展示个人详细信息,如名字,姓氏和电子邮件运行时类:

public class Person() 
{ 
    public String FirstName { get; set;} 
    public String LastName {get; set;} 
    public Email EmailAddress {get; set;} 
} 

,我被填充在运行时从一个DB这个对象,但还需要提供一个设计的实时可视化我想介绍一个IPerson接口定义的合同坚持,即强制执行的财产的getter存在:

public interface IPerson() 
{ 
    String FirstName { get; } 
    String LastName { get; } 
    Email EmailAddress { get; } 
} 

然后我会更新我的运行Person类实现该接口:

public class Person() : IPerson 
{ 
public String FirstName { get; set;} 
public String LastName {get; set;} 
public Email EmailAddress {get; set;} 
} 

然后我会创建一个实现相同的界面和设计时使用

public MockPerson() : IPerson 
{ 
public String FirstName { get { return "John"; } } 
public String LastName { get { return "Smith"; } } 
public Email EmailAddress { get { return new Email("[email protected]"); } } 
} 

提供合理值的模拟类然后,我会实现一种机制,以提供在设计时MockPerson对象,并在运行时的实际Person对象。类似于thisthis。这提供了设计时间数据支持,而不需要运行时间和设计时间环境之间的严格依赖关系。

这种模式非常灵活,可以让您在整个应用程序中提供一致的设计时间数据支持。

+0

为什么我必须解决模拟解决方案?我不希望在设计时看到那张填满了垃圾的表格,我希望每次在我重新编译我的项目之前,我都会注意到它能够看到真实的数据。我可能碰巧在项目的其他部分工作,实际上需要这些数据来做出决定,而无需重新编译。将它与其所有相关的转换一起显示在设计时需要它,而不是将它从数据库中收集出来,这样更方便。 – luvieere 2010-01-21 07:24:00

0

如果你广泛的WPF设计工作使用装饰器等,请使用“上下文”属性/类型

详情: - 在设计时必须modelItem(我假设它的情况下,你知道它)如果没有,那么你可以在

//在DesignAdorner类覆盖实现激活方法的实例是

public class DesignAdorner : PrimarySelectionAdornerProvider 
{ 
     protected override void Activate(ModelItem item) 
     { 
       modelItem = item; 
     } 
} 

现在,您可以访问当前的应用程序使用以下单行代码的提示路径

string aplicationPathDir = System.IO.Directory.GetParent(modelItem.Context.ToString()).FullName; 

让我知道,如果它没有帮助你。

相关问题