ListView 内的 TextBox 绑定到对象,双向绑定不起作用

2024-07-01

Edit:

好吧,在尝试了无数次但没有成功之后,我创建了一个非常小的 Wpf 应用程序。您可以直接复制此代码。请注意,当您更改文本框中的值并按“测试”按钮时,这些值永远不会更新。我不明白为什么双向绑定不起作用。请帮忙。

这是 xaml:

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <ListView Grid.Row="0" 
                 ItemsSource="{Binding Path=Demo.CurrentParameterValue,Mode=TwoWay}" 
                 HorizontalAlignment="Center" VerticalAlignment="Center">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding Path=.,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Width="100"></TextBox>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

        <Button Grid.Row="1" Click="Button_Click">TEST</Button>
    </Grid>

这是 xaml.cs:

namespace WpfApp9
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private VmServiceMethodsViewDataGridModel _demo;

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
        public VmServiceMethodsViewDataGridModel Demo
        {
            get => _demo;
            set
            {
                _demo = value;
                OnPropertyChanged("Demo");
            }
        }

        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            Demo = new VmServiceMethodsViewDataGridModel();
            Demo.CurrentParameterValue.Add(1);
            Demo.CurrentParameterValue.Add(2);
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var collection = Demo.CurrentParameterValue;
            MessageBox.Show(string.Format("Values are {0}, {1}", collection[0], collection[1]));
        }
    }

    public class VmServiceMethodsViewDataGridModel : INotifyPropertyChanged
    {
        private List<object> _currentParameterValue;
        public List<object> CurrentParameterValue
        {
            get => _currentParameterValue;
            set
            {
                _currentParameterValue = value;
                OnPropertyChanged("CurrentParameterValue");
            }
        }

        public VmServiceMethodsViewDataGridModel()
        {
            CurrentParameterValue = new List<object>();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }

绑定的问题在于您试图绑定到一个对象。这在一个完美的OneWay/OneTime设想。但使用绑定时则不然TwoWay。您可以更改属性的值,例如在您的视图模型中,但您无法更改对象实例本身。在您的具体情况下,绑定必须发送新的long输入到视图模型的值集合并替换旧值。当然,这永远不会发生,因为Binding并非旨在以这种方式工作。
技术原因是改变实例就意味着改变Binding.Source。一旦绑定处于活动状态(由BindingExpression)它变得不可变。不允许更改源。这也是原因{Binding Source={DynamicResource ...}}行不通的。这BindingSource只能是静态的(或StaticResource- 不改变资源)。

您通常绑定到属性。在一个TwoWay绑定场景Binding可以简单地更新属性的值。所以解决你的问题的方法就是包装long值到一个类中并绑定TextBox到此类的属性来检索/修改实际值。

在这种情况下,您的代码看起来太复杂了。
您的对象结构太复杂或不自然。

您无需申请DataTemplate to a ContentControl(在 XAML 中)。
当然,由于这是一个 UWP 应用程序,因此请使用x:Bind在可能的情况下,因为这会提高性能。转换器是冗余的,因为Binding and x:Bind允许嵌套PropertyPath e.g.

<ListView ItemsSource="{Binding CurrentParameterValue.ListParameterValues}">

ItemsControl.ItemsSource不需要TwoWay捆绑。这ItemsControl永远不会更新/替换源集合。如果您不打算替换视图模型中的源集合(例如,AtlasMethodParameterList = new ObservableCollection<>()),那么你甚至可以将绑定模式设置为OneTime(这将是默认的x:Bind).
我建议使用OneTime如果您需要替换集合,请致电Clear()在集合上并添加新项目。这将提高性能。

Never use async void在方法签名中,事件处理程序除外。
总是使用async Task,当返回类型为void或者当返回一个值时async Task<TResult>。否则你会遇到意想不到的副作用,尤其是遇到异常时:

// An async void method must return Task
private async Task GetParameterList(string obj)

Also async方法应该always敬请期待。这意味着该方法调用并等待async方法本身必须返回Task or Task<T>值得期待。返回类型的方法void不能等待。

All DependencyProperty每个控件都有自己的Binding.UpdateSourceTrigger set to UpdateSourceTrigger.PropertyChanged默认情况下。
例外是可能引发过多连续属性更改的属性,例如TextBox每次输入/按键都会执行。TextBox.Text默认设置为UpdateSourceTrigger.LostFocus.
你应该删除所有多余的UpdateSourceTrigger.PropertyChanged从绑定中提高可读性。

考虑使用out代替ref如果您不打算读取该变量。如果你只设置值更喜欢使用out向任何读者暗示您的意图。使用in如果不想修改参考(只读参考)。
Your Set方法应该看起来像这样:

protected virtual void Set<TValue>(out TValue valueTarget, TValue value, [CallerMemberName] string propertyName = null)
{
  if (value != valueTarget)
  {
    valueTarget = value;
    OnPropertyChanged(propertyName);
  }
}

我重构了您的完整代码,试图改进它:

参数.cs

// The type that wraps the actual parameter value.
// Consider to use dedicated types e.g., LongParameter instead, to allow a strongly typed Value property instead of a basic property of type object.
// This prevents implicit boxing/unboxing in order to convert from object/reference type to primitive/value type and vice versa. This will improve performance. 
// (Only needed because we are dealing with primitive/value types like long, double, etc)
// You would then have to define a DataTemplate for each type. Don't forget to set x:DataType on each DataTemplate.
public class Parameter : BindableBase
{
  protected Parameter(object value)
  {
    this.Value = value;
  }

  private object value;
  public object Value
  {
    get => this.value;
    set => Set(out this.value, value);
  }
}

VmServiceModel.cs

public class VmServiceModel : BindableBase
{    
  public VmServiceModel()
  {
    this.Parameters = new List<Parameter>();
  }

  private List<Parameter> _parameters;
  public List<Parameter> Parameters
  {
    get => this._parameters;
    set => Set(out this._parameters, value);
  }
}

ViewModel.cs

public class ViewModel : INotifyPropertyChanged
{
  public ViewModel()
  {
    this.AtlasMethodParameterList = new ObservableCollection<VmServiceModel>();
  }

  private ObservableCollection<VmServiceModel> _atlasMethodParameterList;
  public ObservableCollection<VmServiceModel> AtlasMethodParameterList
  {
    get => _atlasMethodParameterList;
    set => Set(out _atlasMethodParameterList, value);
  }

  private async Task GetParameterList(string obj)
  {
    foreach (var item in this.ParametersCollection)
    {
      var vmServiceModel = new VmServiceModel();
      vmServiceModel.Parameters
        .AddRange(item.Value.Cast<long>().Select(innerItem => new Parameter(innerItem)));

      this.AtlasMethodParameterList.Add(vmServiceModel);
    }
  }
}

MainPage.xaml.cs

public sealed partial class MainPage : Page
{
  public ViewModel ViewModel { get; set; }

  public MainPage()
  {
    this.InitializeComponent();
    this.ViewModel = new ViewModel();
  }
}

主页.xaml

<Page>
  <Page.Resources>
    <DataTemplate x:Key="ListIntTemplate" x:DataType="local:VmServiceModel">
      <ListView ItemsSource="{x:Bind Parameters}"
                HorizontalAlignment="Center" 
                SelectionMode="None" Background="Transparent">
        <ListView.ItemsPanel>
          <ItemsPanelTemplate>
            <controls:WrapPanel VerticalAlignment="Top"/>
          </ItemsPanelTemplate>
        </ListView.ItemsPanel>
        <ListView.ItemTemplate>
          <DataTemplate x:DataType="local:Parameter">
            <TextBox Text="{Binding Value Mode=TwoWay}" Height="36" Width="65"/>
          </DataTemplate>
        </ListView.ItemTemplate>
      </ListView>
    </DataTemplate>
  </Page.Resources>

  <Grid>
    <ListView ItemsSource="{x:Bind ViewModel.AtlasMethodParameterList}" 
              ItemTemplate="{StaticResource ListIntTemplate}">
    </ListView>
  </Grid>
</Page>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ListView 内的 TextBox 绑定到对象,双向绑定不起作用 的相关文章

  • 策略模式与依赖注入

    策略模式与依赖注入有何不同 即以下是您可以使用策略模式执行的操作 class Foo private readonly ISortAlgo sortAlgo public Foo ISortAlgo sortAlgo sortAlgo so
  • 规避模板专业化

    假设我是某个模板库的用户 CTL 它定义了一个模板 命名为 Hector template
  • IDeserializationCallback 与 OnDeserializedAttribute

    据我了解 当对象在反序列化后需要执行某些任务时 可以使用 IDeserializationCallback 接口和 OnDeserialized 事件 IDeserializationCallback Serializable public
  • 复制空对象是否涉及访问它

    灵感来自this https stackoverflow com a 48273386 4832499问题 struct E E e E f e Accesses e To access https timsong cpp github i
  • 错误:LNK1120:5 个未解析的外部

    我试图在我的帖子中获取有关已安装应用程序的详细信息 而且 我收到以下错误 Code include
  • 我应该如何继承IDisposable?

    为了保护无辜者 班级名称已更改 如果我有一个名为 ISomeInterface 的接口 我还有继承该接口的类 FirstClass 和 SecondClass FirstClass 使用必须处置的资源 二等舱没有 那么问题来了 我应该从哪里
  • 启动离线 ClickOnce 应用程序并等待退出

    我已经部署了 ClickOnce Windows 窗体应用程序 应用程序 A 另一个应用程序 应用程序 B 以文件名作为参数启动应用程序 A 我用这段代码做到这一点 var basePath Environment GetFolderPat
  • 使用 X509 证书对多个收件人进行 XML 加密和解密

    我已经成功地使用 MSDN 上的示例来加密和解密 xml 文档 http msdn microsoft com en us library ms229744 aspx http msdn microsoft com en us librar
  • 无锁“如果不为零则递减”

    我目前正在用 C 重新发明线程池的轮子 我已经消除了代码中的几乎所有锁 除了以下构造的多个实例之外 std atomic size t counter void produce counter void try consume if cou
  • 在哪里可以查看 LINQ 源代码?

    我需要编写自己版本的 except 方法 或者至少以某种方式修改 LINQ 方法的工作方式 我正在与大型自定义对象列表进行比较 并且需要将匹配项从列表 A 连接到列表 B 我认为除外哈希表构建是进行比较的最快方法 但该方法只会返回非匹配项
  • 尝试写入事件日志时出错 - 无法打开源“SourceName”的日志。您可能没有写入权限

    目前 我们正在尝试将现有的经典 ASP 页面集成到记录事件日志的新方法中 我们通过调用公开为 COM 对象的 NET 程序集来实现此目的 该程序集实际记录到事件日志中 这一切都正常工作 但是当我们尝试写入事件日志时 我们收到错误 无法打开源
  • 在文本文件中搜索字符串的更快方法[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我需要使用 C 在一组文本文件中搜索一个大约 13 个字符的字符串 文本文件的数量正在变化 范围在 100 1000 之间 文件大小范
  • 仅仅“抛出”一次捕获有好处吗?

    与一位同事就他将大部分功能包装在 try catch 中的做法进行了 激烈辩论 但 catch 中只有一个 抛出 例如 Private sub foo try Do something catch throw And nothing els
  • 为什么不允许静态常量浮点数? [复制]

    这个问题在这里已经有答案了 我有一个类 它本质上只是保存了我的应用程序中使用的一堆常量定义 但由于某种原因 longs 编译但是float不 class MY CONSTS public static const long LONG CON
  • C:分段错误:GDB:<读取变量时出错>

    我有一个函数shortestPath 它是Dijkstra算法的修改实现 用于我正在为comp2类开发的棋盘游戏AI 我浏览了网站并使用 gdb 和 valgrind 我确切地知道段错误发生的位置 实际上几个小时前就知道了 但无法弄清楚是什
  • 在heroku上运行c++程序

    我正在尝试在 Heroku 上运行 C 程序 我读过这篇文章 但是我没能成功 因为服务器上没有 g 或 gcc 我尝试像这样将 g 下载到服务器上sudo apt get install g 但是我没有root权限 我还尝试将 g 副本复制
  • 如何将 ContextMenuStrip 添加到 ToolStripMenuItem

    我希望当我单击菜单项时 显示一个包含 删除 重命名 等项目的上下文菜单 当右键单击菜单项时 如何将自身绑定为上下文菜单 我脑海中跳出的第一个想法是连接一些MouseDown事件于ToolStripMenuItem并显示第二个ContextM
  • 如何使用 gcc 的 -I 命令添加递归文件夹

    有没有办法使用 gcc 的 I 命令并通过给出 a 将所有路径添加到搜索路径root目录 我正在尝试使用 gcc E myfile c查看宏展开式 但是myfile c包含不同目录中的一大堆其他头文件 并且因为我在 vim 中执行此命令 所
  • 解析日期时间字符串

    我在使用 DateTime ParseExact 解析 DateTime 字符串时遇到一些困难 DateTime result CultureInfo provider CultureInfo InvariantCulture Parse
  • 相当于 C++ 中用于缓冲读取的 python 生成器

    Guido Van Rossum 在此展示了 Python 的简单性article http neopythonic blogspot com 2008 10 sorting million 32 bit integers in 2mb h

随机推荐

  • 将组合框双向绑定到静态属性

    编辑 所以 我想我的代码是正确的 您所有答案中的代码片段也是正确的 感谢那 我的问题是我的开发机器运行 NET4 5 其行为不同 同样的程序 针对 NET4 0 编译 在 NET4 0 的机器上运行正确 但在 NET4 5 的机器上运行不正
  • Python,将 mongodump 的 bson 输出转换为 json 对象数组(字典)

    我已经使用转储了 mongodb 集合mongodump命令 输出是一个转储目录 其中包含以下文件 dump coll bson coll metadata json 如何将导出的文件打开到在 python 中工作的字典数组中 我尝试了以下
  • 使用 解释 gprof 输出

    我试图在我的程序中找到性能问题 从而通过分析来检测代码 gprof 创建一个如下所示的平面配置文件 Flat profile Each sample counts as 0 01 seconds cumulative self self t
  • 缺乏 CUDA 5 动态并行示例

    我一直在谷歌上搜索 只找到了一个简单的例子 http developer nvidia com sites default files akamai cuda files CUDADownloads TechBrief Dynamic Pa
  • Scrapy在使用crawlerprocess运行时抛出错误

    我用 python 编写了一个脚本 使用 scrapy 来收集网站上不同帖子的名称及其链接 当我从命令行执行脚本时 它可以完美地工作 现在 我的意图是使用运行脚本CrawlerProcess 我在不同的地方寻找类似的问题 但我找不到任何直接
  • 未调用下拉列表的自定义验证器(显然)

    为使用自动回发的下拉列表编写自定义验证器 似乎完全忽略了验证 为什么它被忽略并且有简单的修复方法吗 注意我没有使用 ControlToValidate asp net
  • 从 Iphone 本机客户端使用 Google App Engine 进行身份验证

    我想创建一个 Iphone 游戏 用户可以使用他们的 facebook 凭据登录并通过在 Google App Engine 上运行的我的服务器进行身份验证 我已经在 iPhone 和 Google App Engine 上使用了 Face
  • 如何使用 cmake 和 QRC 将 Qt4 qm 文件集成为二进制文件?

    我有一个 Qt4 CMake 项目 我想将 i18n 的 QM 文件集成到输出二进制文件中 这些是我迄今为止生成 TS 和 QM 文件的规则 set myapp TRANSLATIONS i18n myapp de ts set FILES
  • 同一项目的不同文件夹中的相同包名称

    我正在开发一个大项目 最终可能会包含数万行代码 对于当前的结构我喜欢这样 main go controllers NAME go models NAME go 问题是控制器和模型目录包含很多文件 全部使用package controller
  • 如何在javascript中获取表中复选框的值

    我需要获取表行中提供跨度的复选框的值 下面的代码是我的项目的一部分 HTML 代码用于动态我的表格 而 javascript 代码用于获取不适用于复选框的元素的值 它适用于其他输入元素 我的桌子 var html tr class rows
  • 在 Azure AD B2C 中,首次从社交登录登录时,如何将用户的社交帐户与现有本地帐户关联?

    据我从文档中了解到 Azure AD B2C 会在第一次登录时为来自 GMail Facebook 等社交登录的每个用户创建一个新的本地帐户 如果我错了 请纠正我 但是 我想拦截此行为并将用户链接到已经存在的 用户自己的 本地帐户 而不通过
  • ++ 已弃用,它将在 swift 3 中删除[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 将在 swift 3 中被弃用 变量 现在可以写成 variable 1 我怎样才能重写 variable 请回忆一下之间的区别 varia
  • PHP Serialize() ― 规范 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我正在寻找有关 PHP serial
  • 使用 terraform 初始化 terraform 后端

    我刚刚开始使用 terraform 我希望能够使用 AWS S3 作为后端来存储项目的状态 terraform backend s3 bucket tfstate key app state region us east 1 我觉得使用 t
  • 如何使用判别函数绘制 3 个类别之间的决策边界

    我有 3 个判别函数 将 2D 空间划分为 3 个区域 我想绘制这些区域之间的决策边界 我不知道如何在 python 中使用 matplotlib meshgrid 来做到这一点 对于2个判别函数 过程很简单 我计算值为 0 的函数和等高线
  • 从 canActivate 方法返回 Observable 并在 false 时重定向

    我一直在寻找解决方案但没有运气 如果用户获得授权 我需要调用服务器 并且我需要 canActivate 方法来等待该调用的结果 但我似乎无法将各个部分拼凑在一起 下面是我的代码 我的问题在代码的注释中 canActivate route A
  • 从 Outlook 中提取电子邮件地址

    我正在尝试提取 Outlook 收件箱中所有电子邮件的电子邮件地址 我在互联网上找到了这段代码 Sub GetALLEmailAddresses Dim objFolder As MAPIFolder Dim strEmail As Str
  • NSCollectionView 自定义布局启用滚动

    我无法垂直和水平滚动来使用自定义布局NSCollectionView 根据文档 在我的子类中我返回collectionViewContentSize如果太大 则会在集合视图的封闭滚动视图中自动启用滚动 但是 即使我将所有元素排列在水平行中
  • Select2 的行为与未为 Select2 定义的 Uncaught 查询函数非常不同

    我按以下方式加载 select2 的值 声明类型 var AdjustmentType Backbone Model extend url Hexgen getContextPath referencedata adjustmenttype
  • ListView 内的 TextBox 绑定到对象,双向绑定不起作用

    Edit 好吧 在尝试了无数次但没有成功之后 我创建了一个非常小的 Wpf 应用程序 您可以直接复制此代码 请注意 当您更改文本框中的值并按 测试 按钮时 这些值永远不会更新 我不明白为什么双向绑定不起作用 请帮忙 这是 xaml