我的 WPF 應用程式從相對于主應用程式可執行檔案的位置讀取目錄結構。
然后它將目錄結構可視化為TreeView.
當我只運行應用程式時它作業正常,但是,當我在 XAML 設計器中預覽它時,它不起作用。我發現它是從這樣的不同位置加載的:
C:\Users\Adam\AppData\Local\Microsoft\VisualStudio\17.0_108779a0\Designer\Cache\1481370356x64DA\
是的,這就是System.AppDomain.CurrentDomain.BaseDirectory財產的價值。
我從assembly.Location.
我知道很久以前有人問過類似的問題,答案對以前的 Visual Studio 版本和以前的 .NET 版本有效。它們都不適用于 .NET 6 和 Visual Studio 2022。請不要將其標記為這些問題的重復。
要驗證這些答案不適用于 .NET 6 - 只需創建一個新的 .NET 6 WPF 專案,在視圖執行的任何代碼中插入以下代碼:
throw new Exception($"Path: {System.AppDomain.CurrentDomain.BaseDirectory}");
重新加載設計器,你會明白我在說什么。
我已經找到了一個非常丑陋的解決方法,但它只是hhhhhhideous!當我故意拋出并捕獲例外時。我將在堆疊跟蹤中獲得我的代碼的路徑。然后我可以從那里提取我的專案目錄,然后在專案檔案中找到輸出路徑,就是這樣。但是來吧!必須有更清潔的方法!
更新: 這是hhhhhhideous hack:
using System.IO;
using System.Reflection;
using System.Xml;
static class Abominations {
/// <summary>
/// Gets the calling project's output directory in a hideous way (from debug information). Use when all else fails.
/// </summary>
/// <param name="action">Action that throws an exception.</param>
/// <returns>Calling project's output directory.</returns>
public static string GetCallingProjectOutputDirectory(Action action) {
try {
action();
}
catch (Exception exception) {
var stacktrace = exception.StackTrace!.Split(Environment.NewLine).First();
var p1 = stacktrace.IndexOf(" in ") 4;
var p2 = stacktrace.IndexOf(":line");
var pathLength = p2 - p1;
if (p1 < 0 || p2 < 0 || pathLength < 1) throw new InvalidOperationException("No debug information");
var callingSource = stacktrace[p1..p2];
var directory = new DirectoryInfo(Path.GetDirectoryName(callingSource)!);
FileInfo? projectFile;
do {
projectFile = directory.GetFiles("*.csproj").FirstOrDefault();
if (projectFile is null) directory = directory.Parent!;
}
while (projectFile is null);
var projectXml = new XmlDocument();
projectXml.Load(projectFile.FullName);
var baseOutputPath = projectXml.GetElementsByTagName("BaseOutputPath").OfType<XmlElement>().FirstOrDefault()?.InnerText;
var outputDirectory = directory.FullName;
outputDirectory = baseOutputPath is not null
? Path.GetFullPath(Path.Combine(outputDirectory, baseOutputPath))
: Path.Combine(outputDirectory, "bin");
var buildConfiguration =
Assembly.GetCallingAssembly().GetCustomAttribute<AssemblyConfigurationAttribute>()!.Configuration;
var targetFramework =
projectXml.GetElementsByTagName("TargetFramework").OfType<XmlElement>().FirstOrDefault()!.InnerText;
outputDirectory = Path.Combine(outputDirectory, buildConfiguration, targetFramework);
return outputDirectory;
}
throw new InvalidOperationException("Provided action should throw");
}
}
我測驗了它并且它有效。但這只是一個殘暴的可憎之物,應該被火燒死。
uj5u.com熱心網友回復:
假設你有一個這樣的 DataContext 類:
public class ViewModel
{
public string Path { get; set; }
public ViewModel()
{
Path = AppDomain.CurrentDomain.BaseDirectory;
}
}
如果您對此 Datacontext 進行系結,例如這樣:
<Grid>
<TextBlock Text="{Binding Path}"></TextBlock>
</Grid>
實際上,在設計器和運行時之間找到了不同的路徑。以下是通常適用于此類問題的解決方案:
創建一個派生自 DataContext 類的類,并設定一個測驗值(僅對 Designer 背景關系有效):
public class DesignViewModel : ViewModel
{
public DesignViewModel()
{
Path = "Path for Designer only";
}
}
然后,使用這個類來設定 Designer Datacontext:
d:DataContext="{d:DesignInstance Type=local:DesignViewModel, IsDesignTimeCreatable=True}"
這是一種通過強制為 Designer 設定您想要的值來解決問題的方法。
更新
如果您需要在編譯時(而不是設計時)檢索路徑,CallerFilePathAttribute可能會很有趣。
例子:
public static string GetCompilationPath([System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "")
{
return sourceFilePath;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/422341.html
標籤:
