WPF DataGrid - 禁用时保留选择

2024-04-12

我已经为此苦苦挣扎了一段时间了。我的应用程序中有一个“主/详细信息”布局,并且像许多其他人一样面临着 DataGrid 在禁用它时丢失其选择的问题。本质上,从列表中选择一个元素来填充一系列字段后,用户按下“编辑”,这会禁用 DataGrid 并启用所有表单的字段。按“保存”按钮将在保存数据后恢复这些操作......非常简单。

我在 Windows 7 上使用 VS 2010 在 .Net Framework 4 中进行开发。

我尝试过的:
1)基于这个帖子 http://social.msdn.microsoft.com/Forums/hu-HU/wpf/thread/97920757-a0ed-4488-b1a7-2a2b55fb1014,我曾尝试使用WPF Toolkit 2009年6月版中的DataGrid,但我也有同样的反应。
2)基于此 WPF CodePlex 错误报告 http://wpf.codeplex.com/workitem/13022,我尝试创建一个基于 DataGrid 的自定义控件并重写 OnIsEnabledChanged 调用以删除对“UnselectAllCells”的调用,但由于没有代码示例,我什至无法让它触发一次。我努力了:

public class FormMainDataGrid : DataGrid
{
    static FormMainDataGrid()
    {
        IsEnabledProperty.OverrideMetadata(typeof(FormMainDataGrid), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnIsEnabledChanged)));
    }

    public FormMainDataGrid() : base() { }

    private static void OnIsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        d.CoerceValue(CanUserAddRowsProperty);
        d.CoerceValue(CanUserDeleteRowsProperty);

        //this was added in new version !!!
        /*
        if (!(bool)(e.NewValue))
        {
            ((DataGrid)d).UnselectAllCells();
        }
        */

        // Many commands use IsEnabled to determine if they are enabled or not
        CommandManager.InvalidateRequerySuggested();
    }
}  

但一旦我禁用 DataGrid,这仍然会取消选择当前选定的行。我尝试像这样解释最后的评论(在 Codeplex 错误报告中):

public class FormMainDataGrid : DataGrid
{
    static FormMainDataGrid()
    {

    }

    public static void OverrideStuff() 
    {
        IsEnabledProperty.OverrideMetadata(typeof(FormMainDataGrid), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnIsEnabledChanged)));
    }

    public FormMainDataGrid() : base() { }

    private static void OnIsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        d.CoerceValue(CanUserAddRowsProperty);
        d.CoerceValue(CanUserDeleteRowsProperty);

        //this was added in new version !!!
        /*
        if (!(bool)(e.NewValue))
        {
            ((DataGrid)d).UnselectAllCells();
        }
        */

        // Many commands use IsEnabled to determine if they are enabled or not
        CommandManager.InvalidateRequerySuggested();
    }
}

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        FormMainDataGrid.OverrideStuff();
        base.OnStartup(e);
    }
}  

但这甚至不会触发该方法的修改版本。

首先,我的做法正确吗?考虑到取消选择是由该方法引起的,我可以完全替换我自己的方法对“OnIsEnabledChanged”的内部调用吗? 我还有其他方法可以解决这个问题吗? 或者更具体地说,我如何停止对此方法的基本版本的调用,因为它不是覆盖,因此我不能“不”调用base.OnIsEnabledChanged?

多谢!


供将来参考,如果有人遇到同样的问题。
重新设置 SelectedValue 有很多副作用。
这是覆盖网格上元数据的正确方法:

public class MyDataGrid : DataGrid
{
    static MyDataGrid()
    {
        IsEnabledProperty.OverrideMetadata(typeof(MyDataGrid), new CustomFrameworkPropertyMetadata(OnIsEnabledChanged));
    }

    /// <summary>
    /// Fixes the issue that the DataGrid's selection is cleared whenever the DataGrid is disabled.
    /// Tricky: this issue only happens for 4.0 installations, it is fixed in 4.5 (in-place upgrade) installations.
    /// </summary>
    /// <param name="d"></param>
    /// <param name="e"></param>
    private static void OnIsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        d.CoerceValue(CanUserAddRowsProperty);
        d.CoerceValue(CanUserDeleteRowsProperty);

        //this is there in 4.0 dlls, not in the in-place upgrade 4.5 dlls.
        //if (!(bool)(e.NewValue))
        //{
        //    ((DataGrid)d).UnselectAllCells();
        //}

        CommandManager.InvalidateRequerySuggested();
    }

    class CustomFrameworkPropertyMetadata : FrameworkPropertyMetadata
    {
        public CustomFrameworkPropertyMetadata(PropertyChangedCallback propertyChangedCallback)
            : base(propertyChangedCallback)
        {
        }

        protected override void Merge(PropertyMetadata baseMetadata, DependencyProperty dp)
        {
            // See: http://msdn.microsoft.com/en-us/library/system.windows.propertymetadata.merge.aspx
            // See: http://msdn.microsoft.com/en-us/library/ms751554.aspx
            // By default, PropertyChangedCallbacks are merged from all owners in the inheritance hierarchy,
            // so all callbacks are called whenever the property changes.
            var thisPropertyChangedCallback = this.PropertyChangedCallback;

            base.Merge(baseMetadata, dp);

            // We do NOT want that default behavior here;
            // The callback of DataGrid should not be called here - it clears the selection, we don't want that.
            // But the callback of UIElement should be called here - it visually disabled the element, we still want that.
            if (baseMetadata.PropertyChangedCallback != null)
            {
                Delegate[] invocationList = baseMetadata.PropertyChangedCallback.GetInvocationList();
                PropertyChangedCallback inheritedPropertyChangedCallback = null;
                foreach (var invocation in invocationList)
                {
                    if (invocation.Method.DeclaringType == typeof(DataGrid))
                    {
                        // Do nothing; don't want the callback from DataGrid that clears the selection.
                    }
                    else
                    {
                        inheritedPropertyChangedCallback = inheritedPropertyChangedCallback == null
                            ? (PropertyChangedCallback)invocation
                            : (PropertyChangedCallback)Delegate.Combine(inheritedPropertyChangedCallback, invocation);
                    }

                }
                this.PropertyChangedCallback = thisPropertyChangedCallback != null
                                                   ? (PropertyChangedCallback)Delegate.Combine(inheritedPropertyChangedCallback, thisPropertyChangedCallback)
                                                   : inheritedPropertyChangedCallback;
            }
        }
    }
}

请注意,本文中提到的问题仅发生在 4.0 安装中,未安装 4.5。
它在 .net 4.5 中已“修复”,即使对于面向 4.0 的应用程序也是如此 (“4.5 是就地升级 http://www.hanselman.com/blog/NETVersioningAndMultiTargetingNET45IsAnInplaceUpgradeToNET40.aspx“ 设想 /).

问候,
Koen

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WPF DataGrid - 禁用时保留选择 的相关文章

  • C++11 类型推导与 const char *

    In GotW 94 http herbsutter com 2013 08 12 gotw 94 solution aaa style almost always auto Herb Sutter 对 经典 C 声明进行了区分 const
  • C# 如何比较两个字符串并指出哪些部分不同

    例如 如果我有 string a personil string b personal 我想得到 string c person i l 然而 它不一定是单个字符 我也可以这样 string a disfuncshunal string b
  • flock():在没有竞争条件的情况下删除锁定的文件?

    我使用flock 来实现进程间命名互斥 即某个进程可以决定锁定 some name 这是通过锁定临时目录中名为 some name 的文件来实现的 lockfile tmp some name lock fd open lockfile O
  • 如何使用C#检测IIS版本?

    如何使用C 检测IIS版本 更新 我的意思是来自 winapp 实际上该场景是开发一个自定义安装程序 想要检查已安装 IIS 的版本以调用适当的 api 在这里找到了答案 链接文本 http forums iis net p 1162404
  • 了解左值到右值转换的示例

    我很难理解这段代码 来自 C 14 草案标准的示例 转换拉瓦尔 调用未定义的行为g false 为什么constexpr使程序有效 另外 不访问 是什么意思 y n 在两次通话中g 我们正在返回n数据成员那么为什么最后一行说它不能访问它呢
  • 这些比较应该返回什么?

    我有一个使用 string compare string string 对某些值进行排序的应用程序 我不明白的是为什么 1022 比较小于 10 23 而 10 23 比较小于 1024 是否有特定于 值的东西导致了这个结果 string
  • 如何仅使用 XAML 标记在单击另一个控件时打开 WPF 弹出窗口?

    我有两个控件 一个 TextBlock 和一个 PopUp 当用户在文本块上单击 MouseDown 时 我想显示弹出窗口 我认为我可以使用弹出窗口上的 EventTrigger 来完成此操作 但我不能在 EventTrigger 中使用设
  • Xamarin 中 QR 扫描后的处理对话框

    我在Xamarin应用程序中使用QR码扫描仪 当它扫描QR码时 它会执行一些操作 大约需要一分钟 而在执行操作时 我想在屏幕上显示一个加载对话框 但是 它没有显示在屏幕上 并且在应用程序的其他地方 它运行得很好 Code var expec
  • 未初始化成员的警告在 C++11 上消失

    我编译这个简单的程序 include
  • Cmake 链接到共享库找不到​​库

    在 Ubuntu 上 我有两个目录 build and src In src my CMakeLists txt文件有以下几行 add executable Test main cpp target link libraries Test
  • C# - 当站点上没有活动时,Quartz 调度程序停止运行

    我用quartz调度器创建了asp net站点 该作业正在后台运行 站点上没有其他活动 Quartz 调度程序每 30 分钟调度一次 IIS启动后 Scheduler运行正常 但一段时间后 Scheduler 停止运行 大约 1 小时 如果
  • 托管 C++ 和 AnyCPU

    我有一个托管 C dll 我从 C 项目中引用它 C 项目将被编译为 AnyCPU 有没有办法编译 32 位和 64 位版本的托管 C dll 然后告诉 C 项目在运行时根据正在运行的体系结构加载正确的版本 让 AnyCPU dll 与 C
  • 欢迎消息在网络聊天中不可见,但可以在模拟器中使用

    IConversationUpdateActivity update message using var scope Microsoft Bot Builder Dialogs Internals DialogModule BeginLif
  • 如何保存具有多个缩进设置的XmlDocument?

    我需要保存一个XmlDocument以适当的缩进归档 Formatting Indented 但有些节点及其子节点必须排在一行 Formatting None 从那时起如何实现这一目标XmlTextWriter接受整个文档的设置 在 Ahm
  • 编译使用Basler相机的程序

    我正在尝试使用 Basler 相机捕获图像的 C 程序来工作 我拿到 来自制造商的代码 它应该 非常容易使用 但是 链接它有 成为一场噩梦 我的 C 时代已经过去了 最近只使用 Matlab 所以我可能会犯一些愚蠢的错误 但请赐教 代码如下
  • 消息在事务处理时未到达 MSMQ

    我在本地计算机中创建了一个私有 MSMQ 我使用以下 C 代码将消息发送到队列 当我将队列更改为事务性队列时 消息未到达 MSMQ 但是 Send 方法中没有抛出异常 我需要做出什么改变才能使其发挥作用 using System using
  • C++ 标准是否保证未使用的私有字段会影响 sizeof?

    考虑以下结构 class Foo int a 在 g 中测试 我明白了sizeof Foo 4但这是由标准保证的吗 是否允许编译器注意到a是一个未使用的私有字段并将其从类的内存表示中删除 导致更小的 sizeof 我不希望任何编译器真正进行
  • 如何取消 NetworkStream.ReadAsync 而不关闭流

    我正在尝试使用 NetworkStream ReadAsync 读取数据 但我找不到如何取消调用后的 ReadAsync 作为背景 NetworkStream 由连接的 BluetoothClient 对象 来自 32Feet NET 蓝牙
  • 仅使用 url 嵌入视频

    给定一个 youtube url 我如何使用 net c 将视频嵌入到页面中 只需添加如下一行 将 autoplay 设置为 0 或 1 取决于您是否希望人们真正留在您的页面上
  • 实现“计时器”的最佳方法是什么? [复制]

    这个问题在这里已经有答案了 实现计时器的最佳方法是什么 代码示例会很棒 对于这个问题 最佳 被定义为最可靠 失火次数最少 和最精确 如果我指定 15 秒的间隔 我希望每 15 秒调用一次目标方法 而不是每 10 20 秒调用一次 另一方面

随机推荐

  • 从不同线程写入相邻的数组元素?

    是否有任何现代的常见 CPU 从不同线程同时写入数组的相邻元素是不安全的 我对 x86 特别感兴趣 您可能会认为编译器不会做任何明显荒谬的事情来增加内存粒度 即使它在技术上符合标准 我对编写任意大结构的情况感兴趣 而不仅仅是本机类型 Not
  • 有没有办法在 Linux 上使用 QFileDialog 自动向文件添加扩展名

    我希望用户能够输入将保存为 xml 文件的文件的名称 目前在 Windows 和 Mac 上 如果您输入 test 作为文件名 它会自动添加 xml 这就是我想要的 不幸的是 在测试 Linux 版本时 我发现输入不带扩展名的文件名会保存为
  • 如何安装 Dart v2?

    我浏览了 Dart 官方网站 他们深入探讨了 开发 渠道和 稳定 渠道 但对如何实际安装 SDK 版本一无所知 也没有有关当前稳定版和开发版的信息 显然我错过了隐藏在普通网站中的东西 我想尝试一些官方的 angulardart 组件库 但构
  • ASP.NET Gridview 中没有时间的日期格式

    在 ASP NET gridview 中绑定两个日期 我要显示dd MM yyyy但它显示10 03 2014 00 00 00
  • 如何在 Android 上保持在后台监听推送通知

    我正在研究 Android 中的推送通知 现在的问题是 我想在应用程序启动后立即在后台运行推送通知 因为我不知道服务器何时将数据推送到设备 主要要求是我们的企业应用程序有超过 10 个活动 并且根据收到的通知 我必须将相关活动置于前台 以便
  • 如何使用maven操作Manifest文件

    我有一个用 Maven 构建的 EAR 文件 EAR 包含多个 jar 我需要在清单文件中为其中一个 jar 添加一行 我知道 maven jar plugin 选项 manifestEntries 但这对于单个独立 jar 很有用 而不是
  • MySQL 实体框架错误 - 在配置中找不到指定的存储提供程序,或者指定的存储提供程序无效

    我用 C 编写了一个程序集来执行 MySQL 数据库的所有数据访问 我已在我的 C winform 桌面应用程序中成功使用了该程序集 已编译的 dll 但它仅适用于安装了 MySQL Connector Net 6 4 4 的电脑 我尝试在
  • Java 优化器会删除空方法调用的参数构造吗?

    假设我有这样的代码 log info Now the amount amount seems a bit high 我将用虚拟实现替换 log 方法 例如 class Logger public void info 如果没有检测到副作用 优
  • 如果 call_user_func 返回 false 该怎么办?

    我正在调用的函数call user func应该返回FALSE 那么如果可调用无效 我如何检测错误呢 旁注 为什么他们没有抛出异常而不是返回错误代码 或者有没有办法 捕获 错误 我有一个错误句柄 我应该让它为我抛出异常吗 如果你想检查要调用
  • 如何在 C# 中验证 localhost 的 url

    我在 MVC 中使用 UrlAttribute 但它不接受本地主机网址 例如http localhost GCWeb http localhost GCWeb Url ErrorMessage please enter valid ftp
  • 如何在没有互联网的情况下通过 wifi 提供网站服务?

    我想通过开放的 wifi 连接提供网站服务 但我不希望此 wifi 连接能够访问互联网 这是否可能以及我将如何去做 我已经在本地设置了网站 并通过本地主机或 IP 地址在浏览器中进行了访问 但我不确定如何设置网络服务器并通过 wifi 为网
  • 使用 WPF 对象在另一个对象上“打孔”?

    我有一个椭圆 它只是一个圆 我的问题是我想从大圆的中间切出一个圆形的孔 但似乎没有任何效果 我尝试过不透明蒙版 但没有任何效果 更复杂的是 大圆圈具有 DropShadowEffect 但因为这个圆圈是稍微透明的 所以你可以看到它后面有一个
  • Eclipse 文件搜索模式恰好出现两次

    我想对像所示的人那样的文件进行文件搜索here http jgeeks blogspot com 2013 10 searching multiple words in multiple html 我想找到包含以下内容的文件字符串1和字符串
  • 无法访问类的内部接口

    我有一个用于 recyclerview 的适配器类 public abstract class RecyclerViewArrayAdapter
  • 如何配置 BizTalk WCF-SQL 适配器以从 SQL Server 2012“始终在线”副本数据库获取数据?

    我们有一个客户端将使用 SQL Server 2012 的 AlwaysOn 可用性功能 他们希望将 BizTalk WCF SQL 端口连接到只读副本 The 文档 http technet microsoft com en us lib
  • .net 4.0 中引用类型的 volatile

    我很困惑volatile供参考类型 据我了解 对于原始类型 volatile可以立即反映来自另一个线程的值变化 对于引用类型 可以立即反映地址变化 但是 对象的内容呢 它们仍然被缓存吗 假设List Add 是一个原子操作 例如 我有 cl
  • React Native:执行 UI 块时抛出异常

    我正在构建一个 iOS React Native 应用程序 目前正在使用 React Native swipe card 包为我的应用程序构建 tinder 例如刷卡 该应用程序工作正常 但是当我向左或向右滑动卡片 并在它离开屏幕一半时放开
  • 如何在rails控制器中获取上传文件的文件名

    在我的控制器中 如果我根据建议给出以下内容 filename params upload result filename original filename 我正进入 状态 undefined method original filenam
  • Python 是否有相当于 Java 的 AWT Robot 类? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有谁知道类似的Python类Java机器人 http java sun com javase 6 docs api java awt Ro
  • WPF DataGrid - 禁用时保留选择

    我已经为此苦苦挣扎了一段时间了 我的应用程序中有一个 主 详细信息 布局 并且像许多其他人一样面临着 DataGrid 在禁用它时丢失其选择的问题 本质上 从列表中选择一个元素来填充一系列字段后 用户按下 编辑 这会禁用 DataGrid