WPF DataBinding:取消属性更改 - 组合框未对齐

2024-03-17

我有一个带有组合框和文本框的 WPF 表单(两者都数据绑定到对象的属性)。更改组合框或文本框输入会更新对象的属性,并且数据绑定会启动并更新 UI。问题是,我实现了一种取消更改的方法,该方法有效,但搞砸了 UI 更新。如果我从组合框进行更改并取消它,则组合框不会将所选值恢复为应有的值(由对象的值绑定)。如果我从文本框进行更改并取消它,文本框和组合框都会显示正确的数据,但焦点会立即赋予组合框(当它应该留在文本框上时,因为这是我最后一个地方它)。我不太确定如何在一般方面解决这个问题,而不是处理更改事件并验证更改之后没有被取消(因为那么数据绑定的意义何在?)...

//User.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;

namespace MyTesting
{
    public class User : AbstractEntity
    {
        public User()
        {
            Rankings = new Dictionary<int,string>();

            Rankings.Add(1, "Newbie");
            Rankings.Add(10, "Novice");
            Rankings.Add(25, "Adept User");
            Rankings.Add(50, "Power User");
            Rankings.Add(100, "Admin God");
        }

        public Dictionary<Int32, String> Rankings { get; set; }

        private Int32 _rank;
        public Int32 Rank
        {
            get
            {
                return _rank;
            }
            set
            {
                SetProperty<Int32>("Rank", ref _rank, value);
            }
        }
    }
}


//AbstractEntity.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;

namespace MyTesting
{
    public abstract class AbstractEntity : INotifyPropertyChanging, INotifyPropertyChanged
    {
        protected void SetProperty<T>(String propertyName, ref T property, T value)
        {
            if (!Object.Equals(property, value))
            {
                if (OnPropertyChanging(propertyName, property, value))
                {
                    T oldValue = (T)property;
                    property = value;
                    OnPropertyChanged(propertyName, property, value);
                }
            }
        }

        [field: NonSerialized]
        public event PropertyChangingEventHandler PropertyChanging;

        protected virtual Boolean OnPropertyChanging(String propertyName, Object oldValue = null, Object newValue = null)
        {
            CancellablePropertyChangingEventArgs e;

            if ((oldValue != null) || (newValue != null))
                e = new CancellablePropertyChangingEventArgs(propertyName, oldValue, newValue);
            else
                e = new CancellablePropertyChangingEventArgs(propertyName);

            return OnPropertyChanging(e);
        }
        protected virtual Boolean OnPropertyChanging(CancellablePropertyChangingEventArgs e)
        {
            if (PropertyChanging != null)
                PropertyChanging(this, e as PropertyChangingEventArgs);

            return !e.IsCancelled;
        }

        [field: NonSerialized]
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(String propertyName, Object oldValue = null, Object newValue = null)
        {
            ExtendedPropertyChangedEventArgs e;

            if ((oldValue != null) || (newValue != null))
                e = new ExtendedPropertyChangedEventArgs(propertyName, oldValue, newValue);
            else
                e = new ExtendedPropertyChangedEventArgs(propertyName);

            OnPropertyChanged(e);
        }
        protected virtual void OnPropertyChanged(ExtendedPropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, e as PropertyChangedEventArgs);
        }
    }

    public class ExtendedPropertyChangedEventArgs : PropertyChangedEventArgs
    {
        public ExtendedPropertyChangedEventArgs(String propertyName)
            : base(propertyName)
        {
        }

        public ExtendedPropertyChangedEventArgs(String propertyName, Object oldValue, Object newValue)
            : base(propertyName)
        {
            OldValue = oldValue;
            NewValue = newValue;
        }

        public Object OldValue { get; private set; }
        public Object NewValue { get; private set; }
    }

    public class CancellablePropertyChangingEventArgs : PropertyChangingEventArgs
    {
        public CancellablePropertyChangingEventArgs(String propertyName, Boolean cancel = false)
            : base(propertyName)
        {
            IsCancelled = cancel;
        }

        public CancellablePropertyChangingEventArgs(String propertyName, Object oldValue, Object newValue, Boolean cancel = false)
            : base(propertyName)
        {
            OldValue = oldValue;
            NewValue = newValue;

            IsCancelled = cancel;
        }

        public Object OldValue { get; private set; }
        public Object NewValue { get; private set; }

        public Boolean IsCancelled { get; set; }
    }
}


<!-- MainWindow.xaml -->
<Window x:Class="ObservableDictionaryBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:src="clr-namespace:MyTesting"
        Title="MainWindow" Height="350" Width="525" Loaded="OnLoaded">

    <Grid>
        <ComboBox x:Name="RankList" Height="23" HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="12,12,12,0" />

        <TextBlock Height="23" Width="40" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="13,100,0,0" Text="Rank:" />
        <TextBox x:Name="RankBox" Height="23" HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="59,97,12,0" />
    </Grid>
</Window>

//MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
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 MyTesting
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            MyUser = new User();

            InitializeComponent();

            MyUser.PropertyChanging += new PropertyChangingEventHandler(MyUser_PropertyChanging);
        }

        private User MyUser { get; set; }

        private Binding RankListBinding { get; set; }
        private Binding RankBinding { get; set; }
        private Binding RankListRankBinding { get; set; }

        private void OnLoaded(object sender, EventArgs e)
        {
            DataContext = MyUser;

            RankListBinding = new Binding("Rankings");
            RankListBinding.Source = MyUser;
            RankList.SetBinding(ComboBox.ItemsSourceProperty, RankListBinding);
            RankList.SelectedValuePath = "Key";
            RankList.DisplayMemberPath = "Value";

            RankBinding = new Binding("Rank");
            RankBinding.Source = MyUser;
            RankBox.SetBinding(TextBox.TextProperty, RankBinding);

            RankListRankBinding = new Binding("Rank");
            RankListRankBinding.Source = MyUser;
            RankList.SetBinding(ComboBox.SelectedValueProperty, RankListRankBinding);
        }

        private void MyUser_PropertyChanging(Object sender, PropertyChangingEventArgs e)
        {
            CancellablePropertyChangingEventArgs ea = e as CancellablePropertyChangingEventArgs;

            String text = String.Format("Would you like to change the property '{0}' from '{1}' to '{2}'?",
                    e.PropertyName,
                    (ea.OldValue == null) ? "<null>" : ea.OldValue.ToString(),
                    (ea.NewValue == null) ? "<null>" : ea.NewValue.ToString()
                    );

            MessageBoxResult result = MessageBox.Show(this, text, "Property Changed",
                MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes);

            if (result == MessageBoxResult.No)
                ea.IsCancelled = true;
        }
    }
}

更新的方法:这修复了绑定,但没有解决当用户尝试更改文本框中的值然后取消它时组合框窃取焦点的问题。但是,至少 UI 在数据绑定值方面是匹配的。我找到了这个link http://blog.alner.net/archive/2010/04/25/cancelling-selection-change-in-a-bound-wpf-combo-box.aspx这帮助了我。

protected void SetProperty<T>(String propertyName, ref T property, T value)
{
    if (!Object.Equals(property, value))
    {
        bool cancelled = OnPropertyChanging<T>(propertyName, property, value);

        if (cancelled)
        {
            Application.Current.Dispatcher.BeginInvoke(
                new Action(() =>
                {
                    OnPropertyChanged<T>(propertyName);
                }),
                DispatcherPriority.ContextIdle,
                null
            );

            return;
        }

        T originalValue = property;
        property = value;
        OnPropertyChanged(propertyName, originalValue, property);
    }
}

这解决了 UI 显示正确的数据绑定数据的问题……它只是没有解决焦点被盗的问题:

protected void SetProperty<T>(String propertyName, ref T property, T value)
{
    if (!Object.Equals(property, value))
    {
        bool cancelled = OnPropertyChanging<T>(propertyName, property, value);

        if (cancelled)
        {
            Application.Current.Dispatcher.BeginInvoke(
                new Action(() =>
                {
                    OnPropertyChanged<T>(propertyName);
                }),
                DispatcherPriority.ContextIdle,
                null
            );

            return;
        }

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

WPF DataBinding:取消属性更改 - 组合框未对齐 的相关文章

  • 在 C++ 中分割大文件

    我正在尝试编写一个程序 该程序接受一个大文件 任何类型 并将其分成许多较小的 块 我想我已经有了基本的想法 但由于某种原因我无法创建超过 12 kb 的块大小 我知道谷歌等上有一些解决方案 但我更感兴趣的是了解这个限制的根源是什么 然后实际
  • 如何进行带有偏差的浮点舍入(始终向上或向下舍入)?

    我想以偏置舍入浮动 要么总是向下 要么总是向上 代码中有一个特定的点 我需要这个 程序的其余部分应该像往常一样四舍五入到最接近的值 例如 我想四舍五入到最接近的 1 10 倍数 最接近 7 10 的浮点数约为 0 69999998807 但
  • Blazor 与 Razor

    随着 Blazor 的发明 我想知道这两种语言之间是否存在显着的效率 无论是在代码创建方面还是在代码的实际编译 执行方面 https github com SteveSanderson Blazor https github com Ste
  • 使用实体框架从集合中删除项目

    我正在使用DDD 我有一个 Product 类 它是一个聚合根 public class Product IAggregateRoot public virtual ICollection
  • std::map 和二叉搜索树

    我读过 std map 是使用二叉搜索树数据结构实现的 BST 是一种顺序数据结构 类似于数组中的元素 它将元素存储在 BST 节点中并按其顺序维护元素 例如如果元素小于节点 则将其存储在节点的左侧 如果元素大于节点 则将其存储在节点的右侧
  • 如何在 VS 中键入时显示方法的完整文档?

    标题非常具有描述性 是否有任何扩展可以让我看到我正在输入的方法的完整文档 我想查看文档 因为我可以在对象浏览器中看到它 其中包含参数的描述和所有内容 而不仅仅是一些 摘要 当然可以选择查看所有覆盖 它可能是智能感知的一部分 或者我不知道它并
  • Xamarin Android:获取内存中的所有进程

    有没有办法读取所有进程 而不仅仅是正在运行的进程 如果我对 Android 的理解正确的话 一次只有一个进程在运行 其他所有进程都被冻结 后台进程被忽略 您可以使用以下代码片段获取当前正在运行的所有 Android 应用程序进程 Activ
  • 组合框项目为空但数据源已满

    将列表绑定到组合框后 其 dataSource Count 为 5 但组合框项目计数为 0 怎么会这样 我习惯了 Web 编程 而且这是在 Windows 窗体中进行的 所以不行combo DataBind 方法存在 这里的问题是 我试图以
  • C# 创建数组的数组

    我正在尝试创建一个将使用重复数据的数组数组 如下所示 int list1 new int 4 1 2 3 4 int list2 new int 4 5 6 7 8 int list3 new int 4 1 3 2 1 int list4
  • 如何排列表格中的项目 - MVC3 视图 (Index.cshtml)

    我想使用 ASP NET MVC3 显示特定类型食品样本中存在的不同类型维生素的含量 如何在我的视图 Index cshtml 中显示它 an example 这些是我的代码 table tr th th foreach var m in
  • 在 C 中复制两个相邻字节的最快方法是什么?

    好吧 让我们从最明显的解决方案开始 memcpy Ptr const char a b 2 调用库函数的开销相当大 编译器有时不会优化它 我不会依赖编译器优化 但即使 GCC 很聪明 如果我将程序移植到带有垃圾编译器的更奇特的平台上 我也不
  • UWP 无法在两个应用程序之间创建本地主机连接

    我正在尝试在两个 UWP 应用程序之间设置 TCP 连接 当服务器和客户端在同一个应用程序中运行时 它可以正常工作 但是 当我将服务器部分移动到一个应用程序并将客户端部分移动到另一个应用程序时 ConnectAsync 会引发异常 服务器未
  • C# 搜索目录中包含字符串的所有文件,然后返回该字符串

    使用用户在文本框中输入的内容 我想搜索目录中的哪个文件包含该文本 然后我想解析出信息 但我似乎找不到该字符串或至少返回信息 任何帮助将不胜感激 我当前的代码 private void btnSearchSerial Click object
  • OxyPlot WPF 不适用于按钮单击

    我在使用 OxyPlot 时遇到了一些问题 但无法通过他们的文档或其他搜索来解决 我正在开发一个 wpf 应用程序 它允许用户通过按钮单击事件打开 csv 然后执行一些数学运算并报告一些有用的信息 我想绘制一些生成的数据 因此使用 OxyP
  • 如何检测 C# 中该字典键是否存在?

    我正在使用 Exchange Web 服务托管 API 和联系人数据 我有以下代码 即功能性的 但并不理想 foreach Contact c in contactList string openItemUrl https service
  • 无法使用 Ninject 将依赖项注入到从 Angular 服务调用的 ASP.NET Web API 控制器中

    我将 Ninject 与 ASP NET MVC 4 一起使用 我正在使用存储库 并希望进行构造函数注入以将存储库传递给其中一个控制器 这是实现 StatTracker 接口的上下文对象 EntityFramework public cla
  • 内核开发和 C++ [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 从我know https stackoverflow com questions 580292 what languages are windo
  • 同时从多个流中捕获、最佳方法以及如何减少 CPU 使用率

    我目前正在编写一个应用程序 该应用程序将捕获大量 RTSP 流 在我的例子中为 12 个 并将其显示在 QT 小部件上 当我超过大约 6 7 个流时 问题就会出现 CPU 使用率激增并且出现明显的卡顿 我认为它不是 QT 绘制函数的原因是因
  • 跨项目/dll 访问 Xaml 中的资源

    是否可以从另一个项目引用存储在 ResourceDictionary 构建操作 资源 中的 Xaml 资源 我想将资产合并到主项目的资源字典中或单独访问它们 例如 项目 MyResources 包含一个名为 Assets 的文件夹 其中有一
  • 如何查明CONFIG_FANOTIFY_ACCESS_PERMISSIONS是否启用?

    我想利用fanotify 7 http man7 org linux man pages man7 fanotify 7 html我遇到的问题是在某些内核上CONFIG FANOTIFY ACCESS PERMISSIONS不起作用 虽然C

随机推荐

  • 使用局部变量还是内联链方法更好? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 如果我有一系列方法调用 每个方法的值用于下一次调用 我应该将它们存储在局部变量中 如下所示 DynamicForm filledForm For
  • 在 XAML 中绑定 MapIcon

    我正在尝试使用 MapControl 显示当前查看位置的 MapIcon 在我的 XAML 中 我有
  • 模拟集成测试

    如何模拟集成测试所需的众多依赖项 我使用 Mockito 进行 纯 单元测试 在这种情况下 纯粹 意味着测试单个类 模拟它的所有依赖项 美丽的 现在进行集成测试 假设在这种情况下 集成测试将测试如下内容 消息被放入队列中 消息已 处理 响应
  • 如何在 WooCommerce 中创建多个具有相同 SKU 的简单产品?

    我想在 WooCommerce 中创建多个具有相同 SKU 的简单产品 我在管理设置中搜索 但找不到任何启用此功能的设置 有没有什么钩子可以让我禁用这个功能 如果您想完全禁用 SKU 功能 那么您必须使用wc product sku ena
  • 测试飞行组 - 如何将构建发送到组?

    苹果在 TestFlight Groups 上的公告称 将您的测试人员分组以快速发送构建 提供 单独说明要关注的位置 并将操作应用于 TestFlight 中同时有多位测试人员 我该怎么做呢 我已经设置了我的组 我的版本已上传并通过了 Be
  • 不平衡学习:导入错误:无法导入名称“MultiOutputMixin”

    我已经重新安装了最新的 scikit learn 和不平衡学习 我还检查了所有其他库 以确保它们与不平衡学习兼容 我只想运行一个简单的RandomOverSample 但我收到以下导入错误消息 import imblearn from im
  • 有没有办法可以判断 SMTP 服务器是否期望客户端使用“隐式”SSL 与“显式”SSL 进行连接?

    SSL 可以是 显式 或 隐式 如以下链接所述 http help globalscape com help secureserver2 Explicit versus implicit SS htm http help globalsca
  • 子动态创建的组件与父组件之间的 Angular4 通信

    我有一个 Angular4 组件 一旦用户按下加号按钮 它就会动态创建许多子组件 子组件有一个输入选择 必须在选项选择后向父组件发送信息 子组件由 ComponentFactoryResolver 创建 如下所示 let component
  • 当 defaultRender 设置为非常基本的 ArcRendererConfig() 时,Flutter GoogleChart 饼图不会渲染

    图表按预期显示使用以下饼图小部件 class ABCPieChart extends StatefulWidget override ABCPieChartState createState gt ABCPieChartState clas
  • 在 Silverlight 应用程序中呈现 HTML 内容

    在我们的应用程序之一中 需要在 Silverlight 2 0 容器之一中显示项目符号列表 我们决定使用 HTML 标记文本来实现同样的目的 虽然 Google 上有很多可用的选项 例如覆盖 HTML div 容器等 但我想知道最可行的方法
  • 保存 python TempFile 的快速方法?

    我在用tempfile TemporaryFile进行一些中间处理 该程序在关闭时很好地为我删除了临时文件 这正是我大多数时候想要的行为 但是 有没有办法保存文件以供在发生 陷入 错误或其他异常情况时进行检查 寻找开始并使用shutil c
  • 使用 PHP 获取和存储信用卡信息的最佳实践

    我是否应该在前几个步骤 验证 审查购买 中使用会话 然后在最终提交中将信息输入到数据库中 饼干会被劫持并演变为诉讼吗 是不是风险太大了 如果存储信用卡号 我是否需要以任何特殊方式保护我的数据库 欢迎任何建议和个人经历 信用卡问题对于存储信用
  • Laravel 每个用户一次会话

    我正在尝试找出如何只允许每个用户一个会话 因此 如果有人在已经登录其用户帐户的情况下尝试登录 第一个会话将被销毁 并将被注销以仅允许当前会话 我正在关注这个 如何在 Laravel 中保持每个用户的单个会话 https anupamsaha
  • 如何在应用程序退出前执行代码 flutter

    我想检测用户何时退出我的应用程序并执行一些代码 但我不知道如何执行此操作 我尝试使用这个包 https pub dev packages flutter lifecycle state https pub dev packages flut
  • Mac Catalyst 应用程序:如何在不终止应用程序的情况下关闭窗口?

    我正在使用 Mac Catalyst 开发一个应用程序 当用户关闭 Mac 版本上的窗口时 应用程序将终止 可以通过使用以下方法来改变 Cocoa 中的这种行为 applicationShouldTerminateAfterLastWind
  • 打开一对“int”

    一些背景 我正在解析一个会计分类账 其中有account1 and account2 as int类型 每个都是 0 99999 范围内的数字 我有很多组合需要考虑 理想情况下我想使用类似的东西 switch account1 accoun
  • Rails:验证两列(一起)的唯一性

    我有一个Release模型与medium and country列 等等 不应该有releases共享相同的medium country组合 我该如何将其写为 Rails 验证 您可以使用独特性 http guides rubyonrail
  • if 语句中初始化的变量的范围是什么?

    这可能是一个简单的范围界定问题 Python 文件 模块 中的以下代码让我有点困惑 if name main x 1 print x 在我使用过的其他语言中 这段代码会抛出异常 因为x变量是局部的if语句并且不应该存在于它之外 但是这段代码
  • 仅通过 Express 框架对某些 URL 使用 HTTP 基本身份验证

    我有一个使用 Express 框架设计的 Node js 应用程序http 认证 http http auth info模块 如下 var auth require http auth var express require express
  • WPF DataBinding:取消属性更改 - 组合框未对齐

    我有一个带有组合框和文本框的 WPF 表单 两者都数据绑定到对象的属性 更改组合框或文本框输入会更新对象的属性 并且数据绑定会启动并更新 UI 问题是 我实现了一种取消更改的方法 该方法有效 但搞砸了 UI 更新 如果我从组合框进行更改并取