【问题标题】:btnExample.IsEnabled Assignment Throws Exception in WPFbtnExample.IsEnabled 分配在 WPF 中引发异常
【发布时间】:2014-02-12 22:14:09
【问题描述】:

这是我第一次尝试使用 WPF 构建 C# 应用程序;我过去一直使用 Windows 窗体。我遇到了一个看似简单的任务的错误。当尝试对按钮的.IsEnabled 属性进行以下分配时,PresentationFramework.dll 中会出现异常System.Reflection.TargetIncovationException。当我按下 Break 时,我只是得到 Source Not Available 窗口和选项 ti 查看反汇编信息。

private void txtFileLoc_TextChanged(object sender, TextChangedEventArgs e) {
    if (txtFileLoc.Text.EndsWith(".txt"))
        btnExecute.IsEnabled = true;
    else 
        btnExecute.IsEnabled = false;
}

我已通过将它们替换为 Console.WriteLine 进行调试来验证这是引发异常的赋值。

编辑:根据要求,这里是 XAML 和 CS 程序

<Window x:Name="winMain" x:Class="IP_Extractor_2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="IP Extractor" Height="250" Width="410" ResizeMode="CanMinimize" Background="#FFECEFF4">
    <Grid x:Name="grdMain">
        <Grid.RowDefinitions>
            <RowDefinition Height="39*"/>
            <RowDefinition Height="161*"/>
            <RowDefinition Height="21*"/>
        </Grid.RowDefinitions>
        <ProgressBar x:Name="prgProgress" Margin="0,0,0,0" Grid.Row="2" VerticalAlignment="Bottom" Height="17" Foreground="#FF7A6BA6" Value="50"/>
        <TextBox x:Name="txtFileLoc" HorizontalAlignment="Left" Height="20" Margin="10,10,0,0" Text="Browse for a Text File" VerticalAlignment="Top" Width="290" TextChanged="txtFileLoc_TextChanged"/>
        <Button x:Name="btnBrowse" Content="Browse" HorizontalAlignment="Left" Margin="305,10,0,0" VerticalAlignment="Top" Width="52" Height="20" Click="btnBrowse_Click"/>
        <Button x:Name="btnExecute" Content="Go" HorizontalAlignment="Left" Margin="362,10,0,0" VerticalAlignment="Top" Width="22" Height="20" Click="btnExecute_Click" IsEnabled="False"/>
        <ListBox x:Name="lboResults" HorizontalAlignment="Left" Height="151" Margin="10,0,0,0" Grid.Row="1" VerticalAlignment="Top" Width="374"/>
    </Grid>
</Window>

代码:

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace IP_Extractor_2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        OpenFileDialog openFileDialog1;

        public MainWindow() {
            InitializeComponent();
        }

        private void btnBrowse_Click(object sender, RoutedEventArgs e) {
            // Create an instance of the open file dialog box.
            openFileDialog1 = new OpenFileDialog();

            // Set filter options and filter index.
            openFileDialog1.Filter = "Text Files (.txt)|*.txt";
            openFileDialog1.FilterIndex = 1;
            openFileDialog1.Multiselect = false;

            // Call the ShowDialog method to show the dialog box.
            bool? userClickedOK = openFileDialog1.ShowDialog();

            // Process input if the user clicked OK.
            if (userClickedOK == true)
                txtFileLoc.Text = openFileDialog1.FileName;
        }

        private void txtFileLoc_TextChanged(object sender, TextChangedEventArgs e) {
            if (txtFileLoc.Text.EndsWith(".txt"))
                btnExecute.IsEnabled = true;
            else
                btnExecute.IsEnabled = false;
        }
    }
}

【问题讨论】:

  • 你在ui线程上吗?
  • InnerException 和堆栈跟踪是什么?
  • 创建一个最小的独立程序来重现它,然后发布它。应该可能少于 50 行 cs+xaml。因为这不应该发生,而且有些事情你没有发布。
  • 您的作业看起来不错,应该可以。话虽如此,我们看不到您的应用程序在做什么。
  • @SLaks 抱歉耽搁了。我在 VSE 2013 中找不到这些项目,但在 2010 年会弹出一个有用的异常窗口。InnerException 为空,StackTrace 如下:StackTrace on PasteBin

标签: c# wpf exception button isenabled


【解决方案1】:

在设置之前检查空/空字符串,看看是否会改变。

if (btnExecute != null)
{
    btnExecute.IsEnabled = ((txtFileLoc != null) &&
                            (string.IsNullOrEmpty(txtFileLoc.Text) == false) &&
                            (txtFileLoc.Text.ToLower().EndsWith(".txt")));
}

编辑

虽然代码背后的工作,并且可能是一种有效的方式,但它不是标准方式。 WPF 完全是关于绑定和 INotifyProperty 更改相关的事件。

我会将我的按钮绑定到一个视图模型布尔值,该布尔值将位于页面的数据上下文中(将由按钮继承)并绑定例如

<Button IsEnabled="{Binding IsExecuteButtonOperational }"/>

我建议您开始研究 MVVM 编程范式(将其视为分离业务逻辑表单视图逻辑关注点的方式)。我在我的博客Xaml: ViewModel Main Page Instantiation and Loading Strategy for Easier Binding.上提供了一个示例,可以帮助您入门。

【讨论】:

  • 不幸的是,同样的异常被抛出。
  • @Rawrcasm 我逐字创建了您的代码并遇到了两个错误。首先是当 btnExecute 尚未准备好时,它在初始化期间触发,所以我添加了 if 检查。第二个是当一个文件有 TXT 或 Txt 这样命名时,所以我把 ToLower.试试上面的代码,因为它对我有用。
  • @Rawrcasm 我的意思是说,在您准备好使用我的代码 sn-p 运行的回复后,我然后创建了。所以上面的代码是新的。
  • 感谢您的解决方案,非常感谢。但现在我想知道为什么其他代码在初始化期间/之前运行?我以前从未遇到过这个问题。这是 WPF 特定的吗?如果是这样,最好在尝试设置之前对 everything 进行空检查吗?这似乎很乏味。
  • @Rawrcasm 无论采用何种技术,都应该始终进行空值检查。您正在做的工作是 winform 的方式(是的,您是 winform 程序员),但标准的 WPF 方式是使用 MVVM 编码风格将 IsEnabled 绑定到页面的任何内容数据上下文是具有布尔值的。该布尔值将打开或关闭按钮,并通过后面的代码访问。有关更多信息,请参阅我上面的编辑。
猜你喜欢
  • 2018-11-11
  • 1970-01-01
  • 2018-05-29
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多