【问题标题】:intermittent build problem in a WPF applicationWPF 应用程序中的间歇性构建问题
【发布时间】:2011-07-23 02:38:11
【问题描述】:

我有一个运行了 2 年的大型 WPF 解决方案。现在,当最奇怪的事情发生时,我们正在为该解决方案运行一个自动构建环境。

在我们 50% 的构建中,我收到此错误:

异常:无法转换对象 类型 'System.Windows.Controls.StackPanel' 输入 'System.Windows.Controls.Border'。 对象错误 'System.Windows.Controls.StackPanel' 在标记文件中...

看起来很简单。问题是我背后的代码如下:

<UserControl x:Class="SiSM.Episode.Mishap.SpecializationList" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Converters="clr-namespace:Utils.Converters;assembly=Utils" ...>
    <Border x:Name="root"  BorderThickness="0.5">
        <StackPanel x:Name="stackPanelRoot" VerticalAlignment="Stretch">
            <Grid>
                ...
            </Grid>
            <StackPanel>
                ...
            </StackPanel>
            <ScrollViewer>
                ...
            </ScrollViewer>
        </StackPanel>
    </Border>
</UserControl>

这里出现错误是因为如果我将堆栈面板切换为停靠面板,则错误消息会更改为停靠面板。

我的构建环境如下:

将代码复制到构建文件夹:

private void CopyCode(string sourceDir, string destinationDir) {
            foreach (string dirPath in Directory.GetDirectories(sourceDir, "*", SearchOption.AllDirectories)) {
                if (!dirPath.Contains(".svn") && !dirPath.Contains(@"\bin") && !dirPath.Contains(@"\obj")) {
                    Directory.CreateDirectory(dirPath.Replace(sourceDir, destinationDir));
                }
            }

            foreach (string newPath in Directory.GetFiles(sourceDir, "*.*", SearchOption.AllDirectories)) {
                if (!newPath.Contains(".svn") && !newPath.Contains(@"\bin") && !newPath.Contains(@"\obj")) {
                    string dest = newPath.Replace(sourceDir, destinationDir);
                    File.Copy(newPath, dest);
                }
            }

            Worker.ReportProgress(5, "Copy done");
        }

并构建解决方案:

private void Compile(string buildConfiguration) {
            Engine engine = new Engine();

            FileLogger logger = new FileLogger { Parameters = @"logfile=C:\builds\build.log" };
            engine.RegisterLogger(logger);

            BuildPropertyGroup bpg = new BuildPropertyGroup();
            bpg.SetProperty("Configuration", buildConfiguration, true);
            engine.GlobalProperties = bpg;

            var project = new Project(engine);
            project.Load(ProjectFilePath);

            bool success = engine.BuildProject(project);

            engine.UnregisterAllLoggers();
}

这里有什么问题吗,或者 WPF 和 Microsoft 构建引擎是否存在任何已知问题?

编辑 1

我发现错误发生的时候。如果我第一次运行自动构建应用程序,它总是会成功,但如果我运行它几秒钟,就会发生上述错误。所以这可能是我忘记关闭导致错误的原因。

我在 Compile 方法的末尾添加了一个engine.Shutdown();,但它并没有解决问题。

编辑 2

感谢@swiszcz 的建议,刚刚发现了最奇怪的东西。文件 SpecializationList.g.cs(在 obj 文件夹上)在第一次和第二次构建之间发生变化

第一次构建

void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
this.stackPanelRoot = ((System.Windows.Controls.StackPanel)(target));
return;
case 2:

#line 63 "..\..\..\Mishap\SpecializationList.xaml"
((System.Windows.Controls.Button)(target)).Click += new System.Windows.RoutedEventHandler(this.buttonShowGlobalView_Click);
...

第二次构建

void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 2:
this.stackPanelRoot = ((System.Windows.Controls.StackPanel)(target));
return;
case 3:
...

它在切换条件下增加 1,而在第二次构建时,他无法将 Button(案例 2)转换为 StackPanel(案例 1)。

【问题讨论】:

  • 您是否有可能同时运行两个构建?他们最终会共享一个用于代码生成的文件夹,这可能会导致这类问题。
  • 我使用一个应用程序来构建解决方案,但我只运行了 1 个。加上那个应用程序上的断点告诉我每次只运行一个构建。此外,我在每次构建之前手动删除代码文件夹(如果我忘记这样做,应用程序将发送警告并停止构建过程)。
  • 这个question可能是相关的。
  • 可能是,堆栈跟踪类似。可悲的是它仍然无人问津
  • 您是否像其他问题一样使用 Clickonce 部署?

标签: c# wpf build


【解决方案1】:

我的猜测:当我遇到一个非常类似的错误时,它是由 erroreus .g.cs 文件生成引起的。查看 .g.cs 文件以将 stackPanelRoot 转换为 Border。 xaml 中的解决方法:将 x:Name="stackPanelRoot" 更改为 Name="stackPanelRoot",或删除 x:Name(如果可能)。

【讨论】:

  • 我将 x:Name 更改为 Name。无法删除它,因为我在后面的代码中使用它。至于 .g.cs 文件,似乎还可以。对 stackPanelRoot 的唯一两个引用是内部 System.Windows.Controls.StackPanel stackPanelRoot;和 this.stackPanelRoot = ((System.Windows.Controls.StackPanel)(target));
  • 等等...我错了...如果是:“无法将'System.Windows.Controls.StackPanel'类型的对象转换为'System.Windows.Controls.Border'”然后您可能会将您的 StackPanel 分配给边框“根”。在我们遇到的一个错误中,可以删除控件的名称,这解决了问题。
  • 我很困惑。要删除 Border 名称或 StackPanel 名称?
  • 所以在你的 g.cs 中检查 this.root。或者尝试删除边框的“根”名称。
  • 在 g.cs 上我有两个对根元素的引用:内部 System.Windows.Controls.Border 根;和 this.root = ((System.Windows.Controls.Border)(target));
猜你喜欢
  • 1970-01-01
  • 2010-12-10
  • 2010-09-16
  • 1970-01-01
  • 2015-01-24
  • 1970-01-01
  • 1970-01-01
  • 2014-09-15
  • 2012-01-11
相关资源
最近更新 更多