如何在设计时从我的WPF应用程序获取应用程序的目录?

时间:2009-11-27 13:42:26

标签: c# .net wpf working-directory

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

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

5 个答案:

答案 0 :(得分:6)

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

在这种情况下,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 2008的WPF Designer工具中演示此工作:

  1. 将此代码放在“WPF自定义控件库”或“类库”项目中
  2. 添加读取数据库所需的任何代码并返回显示的数据(在我的情况下,我只是将应用程序目录本身作为字符串返回)
  3. 从您正在设计的项目中引用库项目
  4. 使用XAML文件中的自定义控件或类来填充DataContext或以其他方式向UI提供数据(在我的情况下,我使用x:Static绑定DataContext)
  5. 使用“Windows Presentation Foundation Designer”编辑该XAML文件,只需双击即可完成,除非您更改了默认编辑器,在这种情况下使用“打开方式...”
  6. 当您按照这些步骤操作时,您正在查看的对象将在运行时和设计时以相同的方式填充数据库中的数据。

    还有其他方案可以使用相同的技术,并且根据您的需要还有其他可用解决方案。如果您的需求与我上面假设的不同,请告诉我们。例如,如果您正在编写VS.NET加载项,那么您将处于完全不同的球类游戏中。

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

如果您正在广泛使用使用adorner等的WPF设计师,请使用" Context"属性/类型

<强>详细信息: - 在设计时你有modelItem的实例(我假设它,你知道)如果没有那么你可以在Override实现的Activate方法中实例化它

//在DesignAdorner类

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

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

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

如果它对您没有帮助,请告诉我。

答案 4 :(得分:-2)

好的,这里有进一步的说明是我会做的。

与GraemeF提出的关注保持一致,做你想做的事情是脆弱的,并且最多容易破坏。

因此,通常的做法是将设计时数据支持视为与运行时数据支持完全不同的方法。很简单,您在设计时环境和此DB之间创建的耦合是一个坏主意。

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

所以举个例子。如果我有一个运行时类,需要显示人员详细信息,如名字,姓氏和电子邮件:

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("John@smith.com"); } }
}

然后我将实现一种机制,在设计时提供MockPerson对象,在运行时提供真实的Person对象。类似于thisthis的内容。这提供了设计时数据支持,而没有运行时和设计时环境之间的硬依赖性。

此模式更加灵活,可让您在整个应用程序中提供一致的设计时数据支持。