代码之家  ›  专栏  ›  技术社区  ›  luvieere

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

  •  4
  • luvieere  · 技术社区  · 15 年前

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

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

    5 回复  |  直到 7 年前
        1
  •  6
  •   Ray Burns    15 年前

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

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

      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演示文稿基础设计器”编辑XAML文件,这可以通过双击来完成,除非您更改了默认编辑器,在这种情况下,使用“打开…”

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

    在其他情况下,同样的技术也同样有效,根据您的需要,还有其他解决方案可用。如果您的需求与我上面假设的不同,请告诉我们。例如,如果您正在编写一个vs.net加载项,则说明您正在进行完全不同的球赛。

        2
  •  0
  •   Brad Cunningham    15 年前

    您是否试图支持设计器(如Visual Studio设计器或Blend)?

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

    也许你可以更全面地解释你试图解决的问题,这样我们就能提供一个更好的答案?

        3
  •  0
  •   GraemeF    15 年前

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

    • 这个项目已经建成了吗?
    • 如果没有,就没有可执行文件来获取路径,那么呢?
    • 如果没有建立其他文件,或者它们是建立人工制品,这些文件会存在吗?
    • 如果它是建的,它建在哪里?
    • 是否需要考虑其他IDE?

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

        4
  •  0
  •   Manish Dubey    7 年前

    如果您正在使用Adorner等广泛地使用WPF设计器,请使用“Context”属性/类型

    细节: 在设计时,您有ModelItem的实例(我假设它,您知道它),如果没有,那么您可以在重写activate方法的实现中实例化它。

    //在DesigneAdorner类中

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

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

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

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

        5
  •  -2
  •   Brad Cunningham    15 年前

    好吧,我想进一步澄清一下。

    与格雷姆提出的担忧保持一致,做你想做的事情是脆弱的,最好是容易破碎的。

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

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

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

    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对象。类似的东西 this this . 这提供了设计时数据支持,而不需要运行时和设计时环境之间的硬依赖关系。

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