4

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

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

4

5 回答 5

6

从您的描述看来,您的代码实际上是在 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 2008 的 WPF 设计器工具中演示此工作:

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

当您按照这些步骤操作时,您正在查看的对象将在运行时和设计时以相同的方式填充数据库中的数据。

在其他场景中,同样的技术也同样有效,根据您的需要,还有其他可用的解决方案。如果您的需求与我上面假设的不同,请告诉我们。例如,如果您正在编写一个 VS.NET 插件,那么您就处于一个完全不同的球赛中。

于 2010-01-21T07:21:37.630 回答
0

我认为这是不可能的 - 您正在询问可能尚未构建的程序集的位置。您的设计时代码不会在您的应用程序中运行,并且必须对 IDE 做出一些假设。这对我来说是错误和脆弱的——考虑以下问题:

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

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

于 2009-11-27T13:50:59.070 回答
0

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

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

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

于 2009-11-27T19:30:57.763 回答
0

如果您正在使用装饰器等广泛使用 WPF 设计器,请使用“上下文”属性/类型

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

// 在 DesignAdorner 类中

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

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

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

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

于 2017-06-05T12:52:45.367 回答
-2

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

与 GraemeF 提出的担忧保持一致,做你想做的事是脆弱的,充其量也容易崩溃。

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

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

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

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

我在运行时从数据库中填充这个对象,但还需要提供设计时可视化我将引入一个 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 对象。像这样这样的东西。这提供了设计时数据支持,而没有运行时和设计时环境之间的硬依赖。

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

于 2010-01-21T05:30:48.940 回答