inotifypropertychanged 相关问题

INotifyPropertyChanged是Microsoft .NET中定义的接口,用于通知侦听器对对象所做的数据更改。这些通知使数据绑定的UI控件能够在绑定的数据属性发生更改时自动更新其显示。

.NET MAUI:想要将父对象传递给转换器和控件,但没有收到 OnPropertyChanged

我在 MAUI 中不断遇到这个问题,我怀疑这是由于对 MVVM 的一些基本误解造成的。 假设我有: 公共类学生:ObservableObject { [ObservableProperty] 字符串 _nam...

回答 1 投票 0

根据表格(DataGrid)的选定行设置按钮(ICommand)的操作

我有一个窗口 WPF 和 2 个表 DataGrid。 DataContext 绑定到类 PersonalTaskClassPickerViewModel.cs。 PersonalTaskClassPicker.xaml 我有一个窗口 WPF 和 2 个表 DataGrid。 DataContext 绑定到类 PersonalTaskClassPickerViewModel.cs。 PersonalTaskClassPicker.xaml <Window x:Class="WpfAppTaskPlanner.PersonalTaskClassPicker" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:viewModels="clr-namespace:WpfAppTaskPlanner.ViewModels" xmlns:views="clr-namespace:WpfAppTaskPlanner" xmlns:taskClassDirectory="clr-namespace:Library.TaskClassDirectory;assembly=Library" mc:Ignorable="d" Title="MainWindow" Height="850" Width="1500" d:DataContext="{d:DesignInstance viewModels:PersonalTaskClassPickerViewModel}"> <Window.Resources> <viewModels:OutputValueConverter x:Key="OutputValueConverter"></viewModels:OutputValueConverter> <DataTemplate x:Key="CustomDataGridHeaderTemplate"> <views:CustomDataGridHeader></views:CustomDataGridHeader> </DataTemplate> </Window.Resources> <DockPanel LastChildFill="True"> <StackPanel Orientation="Horizontal" FlowDirection="RightToLeft" DockPanel.Dock="Bottom"> <!--Other buttons--> <Button HorizontalAlignment="Center" VerticalAlignment="Center" Content="Удалить задачу" Width="100" Height="40" Margin="15 5" Command="{Binding RemoveTaskClassCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"/> </StackPanel> <StackPanel DockPanel.Dock="Top"> <TextBlock Text="Связанные задачи" Margin="0 5"></TextBlock> <DataGrid x:Name="DataGridRelatedPersonalTaskClass" DockPanel.Dock="Top" ItemsSource="{Binding SelectedTaskPerformerClass.PersonalTaskClassLists.RelatedList, FallbackValue='SelectedTaskPerformerClass не не выбран'}" SelectedItem="{Binding SelectedTaskClass, Mode=TwoWay}"> <DataGrid.Columns> <DataGridTextColumn Header="Участок" HeaderTemplate="{StaticResource CustomDataGridHeaderTemplate}" Binding="{Binding BrigadeIndex}" IsReadOnly="True"/> <!--Other DataGridTextColumns--> </DataGrid.Columns> </DataGrid> <TextBlock Text="Удаленные задачи" Margin="0 5"></TextBlock> <DataGrid x:Name="DataGridDeletedPersonalTaskClass" DockPanel.Dock="Bottom" ItemsSource="{Binding SelectedTaskPerformerClass.PersonalTaskClassLists.DeletedList, FallbackValue='SelectedTaskPerformerClass не не выбран'}" SelectedItem="{Binding SelectedTaskClass, Mode=TwoWay}"> <DataGrid.Columns> <DataGridTextColumn Header="Участок" HeaderTemplate="{StaticResource CustomDataGridHeaderTemplate}" Binding="{Binding BrigadeIndex}" IsReadOnly="True"/> <!--Other DataGridTextColumns--> </DataGrid.Columns> </DataGrid> </StackPanel> </DockPanel> </Window> PersonalTaskClassPicker.xaml.cs public partial class PersonalTaskClassPicker { public PersonalTaskClassPicker(ref TaskPerformerClass selectedTaskPerformerClass) { InitializeComponent(); DataContext = new PersonalTaskClassPickerViewModel(ref selectedTaskPerformerClass); } } PersonalTaskClassPickerViewModel.cs public class PersonalTaskClassPickerViewModel: BaseViewModel { public PersonalTaskClassPickerViewModel(ref TaskPerformerClass selectedTaskPerformerClass) { RemoveTaskClassCommand = new RelayCommand(RemoveTaskClass, CanRemoveTaskClass); // Other ICommand's } } BaseViewModel.cs public class BaseViewModel : BaseNotifyPropertyChanged { private TaskClass? _selectedTaskClass; public TaskClass? SelectedTaskClass { get => _selectedTaskClass; set { if (Equals(value, _selectedTaskClass)) { return; } if (SetField(ref _selectedTaskClass, value)) { CallRaiseCanExecuteChanged(RemoveTaskClassCommand); } } } private TaskPerformerClass? _selectedTaskPerformerClass; public TaskPerformerClass? SelectedTaskPerformerClass { get => _selectedTaskPerformerClass; set { if (_selectedTaskPerformerClass != value) { _selectedTaskPerformerClass = value; OnPropertyChanged(); } } } public ICommand? RemoveTaskClassCommand { get; protected init; } public static void CallRaiseCanExecuteChanged(ICommand? command) { switch (command) { case AsyncRelayCommandWithParameter getToWorkCommand: getToWorkCommand.RaiseCanExecuteChanged(); break; case RelayCommand getToWorkCommand: getToWorkCommand.RaiseCanExecuteChanged(); break; } } protected bool CanRemoveTaskClass(object parameter) { if (parameter is not PersonalTaskClassPicker { DataContext: PersonalTaskClassPickerViewModel personalTaskClassPickerViewModel }) { return false; } if (personalTaskClassPickerViewModel.SelectedTaskPerformerClass is null) { MessageBox.Show("personalTaskClassPickerViewModel.SelectedTaskPerformerClass is null"); } else { var taskPerformer = personalTaskClassPickerViewModel.SelectedTaskPerformerClass; if (SelectedTaskClass is not null && taskPerformer.PersonalTaskClassLists.RelatedList is not null && taskPerformer.PersonalTaskClassLists.RelatedList.Contains(SelectedTaskClass)) { return true; } } return false; } protected void RemoveTaskClass(object parameter) { if (parameter is not PersonalTaskClassPicker { DataContext: PersonalTaskClassPickerViewModel personalTaskClassPickerViewModel }) { return; } if (personalTaskClassPickerViewModel.SelectedTaskPerformerClass is null) { MessageBox.Show("personalTaskClassPickerViewModel.SelectedTaskPerformerClass is null"); } else { var personalTaskClassListsOfTaskPerformerClass = personalTaskClassPickerViewModel.SelectedTaskPerformerClass.PersonalTaskClassLists; var selectedTaskClass = SelectedTaskClass; if (selectedTaskClass is not null && personalTaskClassListsOfTaskPerformerClass.RelatedList is not null && personalTaskClassListsOfTaskPerformerClass.RelatedList.Contains(selectedTaskClass)) { personalTaskClassListsOfTaskPerformerClass.RelatedList.Remove(selectedTaskClass); personalTaskClassListsOfTaskPerformerClass.DeletedList ??= new ObservableCollection<TaskClass>(); personalTaskClassListsOfTaskPerformerClass.DeletedList.Add(selectedTaskClass); personalTaskClassListsOfTaskPerformerClass.OnPropertyChanged( nameof(personalTaskClassListsOfTaskPerformerClass.RelatedList) ); personalTaskClassListsOfTaskPerformerClass.OnPropertyChanged( nameof(personalTaskClassListsOfTaskPerformerClass.DeletedList) ); CallRaiseCanExecuteChanged(RemoveTaskClassCommand); } } } } BaseNotifyPropertyChanged.cs public class BaseNotifyPropertyChanged : INotifyPropertyChanged { public event PropertyChangedEventHandler? PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null) { if (EqualityComparer<T>.Default.Equals(field, value)) { return false; } field = value; OnPropertyChanged(propertyName); return true; } protected class RelayCommand : ICommand { private readonly Action<object> _execute; private readonly Predicate<object>? _canExecute; public RelayCommand(Action<object> execute, Predicate<object>? canExecute = null) { _execute = execute ?? throw new ArgumentNullException(nameof(execute)); _canExecute = canExecute; } public bool CanExecute(object? parameter) => _canExecute == null || _canExecute(parameter ?? "<N/A>"); public void Execute(object? parameter) { _execute(parameter ?? "<N/A>"); } public event EventHandler? CanExecuteChanged { add => CommandManager.RequerySuggested += value; remove => CommandManager.RequerySuggested -= value; } public void RaiseCanExecuteChanged() { CommandManager.InvalidateRequerySuggested(); } } //Other AsyncRelayCommand's } 从主 WPF 窗口调用 WPF 窗口,如下所示: public class MainViewModel : BaseViewModel { //Other code private static void OnEditPersonalTaskClassList(object parameter) { if (parameter is not TaskPerformerClass selectedTaskPerformerClass) { return; } var personalTaskClassEditor = new PersonalTaskClassPicker(ref selectedTaskPerformerClass); if (personalTaskClassEditor.ShowDialog() == true) { //Other commands } else { MessageBox.Show("DataContext закрытого окна не является типом TaskPerformerClass"); } } } TaskPerformerClass.cs namespace Library.TaskPerformerDirectory; public sealed class TaskPerformerClass : INotifyPropertyChanged { //Other private values private PersonalTaskClassCollection _personalTaskClassLists = null!; private TaskPerformerClass() { } public TaskPerformerClass( FullNameOfThePerson fullName, WorkDay workDay, CalendarYearOfTaskPerformer calendarYearOfTaskPerformer, int bitrixEmployeeIndex, List<Department>? bitrixEmployeeDepartmentList = null, TaskClass? actualTask = null ) { //Other initializations of properties PersonalTaskClassLists = new PersonalTaskClassCollection(this); } //Other property public PersonalTaskClassCollection PersonalTaskClassLists { get => _personalTaskClassLists; set { if (Equals(value, _personalTaskClassLists)) { return; } _personalTaskClassLists = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler? PropertyChanged; public void OnPropertyChanged([CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null) { if (EqualityComparer<T>.Default.Equals(field, value)) { return false; } field = value; OnPropertyChanged(propertyName); return true; } } PersonalTaskClassCollection.cs public sealed class PersonalTaskClassCollection : INotifyPropertyChanged { private int _id; private int _taskPerformerClassId; private TaskPerformerClass _taskPerformerClass = null!; private ObservableCollection<TaskClass>? _completedList; private ObservableCollection<TaskClass>? _deletedList; private ObservableCollection<TaskClass>? _relatedList; private PersonalTaskClassCollection() { } public PersonalTaskClassCollection(TaskPerformerClass taskPerformerClass) => TaskPerformerClass = taskPerformerClass; public int Id { get => _id; set { if (value == _id) { return; } _id = value; OnPropertyChanged(); } } public int TaskPerformerClassId { get => _taskPerformerClassId; set { if (value == _taskPerformerClassId) { return; } _taskPerformerClassId = value; OnPropertyChanged(); } } public TaskPerformerClass TaskPerformerClass { get => _taskPerformerClass; set { if (Equals(value, _taskPerformerClass)) { return; } _taskPerformerClass = value; OnPropertyChanged(); } } public ObservableCollection<TaskClass>? RelatedList { get => _relatedList; set { if (Equals(value, _relatedList)) { return; } _relatedList = value; OnPropertyChanged(); } } public ObservableCollection<TaskClass>? DeletedList { get => _deletedList; set { if (Equals(value, _deletedList)) { return; } _deletedList = value; OnPropertyChanged(); } } public ObservableCollection<TaskClass>? CompletedList { get => _completedList; set { if (Equals(value, _completedList)) { return; } _completedList = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler? PropertyChanged; public void OnPropertyChanged([CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null) { if (EqualityComparer<T>.Default.Equals(field, value)) { return false; } field = value; OnPropertyChanged(propertyName); return true; } } 我认为描述“TaskClass.cs”类没有任何意义。它只是一个包含任务属性的类。 在“DataGridRelatedPersonalTaskClass”和“DataGridDeletedPersonalTaskClass”这两个表中随机选择一行后,“RemoveTaskClassCommand”按钮将永远无法更改“set”属性“SelectedTaskClass”的值。因此,如果单击它,“DataGridRelatedPersonalTaskClass”中下一个突出显示的任务将被删除。 随着时间的推移,我意识到,如果我突出显示表中的每个问题,那么每个“DataGrid”的“SelectedItem”属性将继续处于活动状态,但我的“SelectedTaskClass”属性并不总是更新。尽管“IsMouseOver”属性始终正确显示我最后突出显示的表中的行。 当选择“DataGridRelatedPersonalTaskClass”表中的一行时,我想正确配置“RemoveTaskClassCommand”按钮的活动。怎么办? 首先,有一个重要的说明。您传递 Window 命令参数 CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"。 由于此命令是一个 ViewModel 实体,并且根据 MVVM 规则,禁止将任何 UI 元素传递给 ViewModel,那么您的实现实际上完全破坏了 MVVM 合规性。 关于你问题的本质。 您的任务的可能实现选项之一的最简化示例。 namespace Core2024.SO.Zhan.question79147702 { public class SomeTextItem { private string _title = string.Empty; private string _text = string.Empty; private string _description = string.Empty; public string Title { get => _title; set => _title = value ?? string.Empty; } public string Text { get => _text; set => _text = value ?? string.Empty; } public string Description { get => _description; set => _description = value ?? string.Empty; } } } using Simplified; // This is the space with my implementation of INotifyPropertyChanged and ICommand interfaces. You can use your own implementations instead. using System.Collections.ObjectModel; namespace Core2024.SO.Zhan.question79147702 { public class SomeTextViewModel { private const string data = "After randomly selecting a row in each of the 2 tables \"DataGridRelatedPersonalTaskClass\" and \"DataGridDeletedPersonalTaskClass\", the \"RemoveTaskClassCommand\" button will never be able to change the value of the \"set\" property \"SelectedTaskClass\". Thus, if you click on it, the next highlighted task in the \"DataGridRelatedPersonalTaskClass\" will be deleted. Over time, I realized that if I highlighted each question in the tables, then the \"SelectedItem\" properties of each \"DataGrid\" continue to be active, but my \"SelectedTaskClass\" property is not always updated.Although the \"IsMouseOver\" property always correctly displays the row in which table I highlighted last."; private static IEnumerable<SomeTextItem> GetItems() { string[] split = data.Split(); for (int i = 2; i < split.Length; i+=3) { yield return new SomeTextItem() { Title = split[i-2], Text = split[i-1], Description = split[i] }; } } public SomeTextViewModel() { TextItems = new ObservableCollection<SomeTextItem>(GetItems()); RemoveTextItem = new RelayCommand<SomeTextItem> ( item => TextItems.Remove(item), item => TextItems.Contains(item) ); } public ObservableCollection<SomeTextItem> TextItems { get; } public RelayCommand RemoveTextItem { get; } } } <Window x:Class="Core2024.SO.Zhan.question79147702.SomeTextWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Core2024.SO.Zhan.question79147702" mc:Ignorable="d" Title="SomeTextWindow" Height="450" Width="800" DataContext="{DynamicResource vm}"> <Window.Resources> <local:SomeTextViewModel x:Key="vm"/> </Window.Resources> <Grid> <DataGrid ItemsSource="{Binding TextItems}"> <DataGrid.Columns> <DataGridTemplateColumn> <DataGridTemplateColumn.CellTemplate> <DataTemplate DataType="{x:Type local:SomeTextItem}"> <Button Content="Remove Item" CommandParameter="{Binding Mode=OneWay}" Command="{Binding RemoveTextItem, Mode=OneWay, Source={StaticResource vm}}"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> </Grid> </Window>

回答 1 投票 0

OnPropertyChanged 在 Blazor(MAUI 混合)中无法正常工作

我已经在 MauiProgram.cs 中注册了一个服务: builder.Services.AddSingleton(); 服务等级: 公共类 NetworkStatusService :INotifyPropertyChanged { 私人

回答 1 投票 0

WPF DataContext PropertyChanged 为空

我有两个 WPF 组件,一个包含另一个的列表。 我在父 WPF 组件中设置了 DataContext,因此我可以定义一个属性。 不幸的是,我的模型的 PropertyChanged 是

回答 1 投票 0

访问视图模型之间的依赖属性

我有 2 个视图模型, viewmodel 绑定到 view A 类:INotifyPropertyChanged { 公共 A(){} 私人布尔_propertya; 公共 bool 属性A { 获取{返回_propertya;} 设置{_propertya=值;

回答 1 投票 0

C# WPF 依赖值未更新

我正在使用 WPF 开发 C# .NET 6.0 项目,并且有以下场景: 我的 WPF 应用程序中有两个文本框: 费用比例: <

回答 1 投票 0

C# WPF 依赖值未更新

我正在使用 WPF 开发 C# .NET 6.0 项目,并且有以下场景: 我的 WPF 应用程序中有两个文本框: 费用比例: ...

回答 1 投票 0

C 定义类

`我需要有关 IPropertyChanged 的帮助,如何操作才能正常工作。 `C# 如何使用 IPropertyChanged 创建对象类? 我尝试在课堂上这样做,但它不起作用,我需要以某种方式查...

回答 1 投票 0

DataGrid 中的 CheckBox 不会触发绑定源中的属性更改

我有一个显示项目列表的 DataGrid 每行都有一个复选框,应更改相应数据类中的布尔字段 我预计字段值会发生变化并且

回答 1 投票 0

WPF - INotifyPropertyChanged 到父数据 - 不会在从复选框更改值时触发

我有一个显示项目列表的 DataGrid 每行都有一个复选框,应更改相应数据类中的布尔字段 我预计字段值会发生变化并且

回答 1 投票 0

将一个对象分配给另一个对象不会引发 WPF 中的 PropertyChanged 事件

我尝试在一个非常简单(且有效)的项目中隔离我的问题。假设我有一个包含 2 个字段的简单模型,并且我已经配置了其属性和 PropertyChanged 事件。这是一个

回答 1 投票 0

如何解决由qml中的属性更改引起的循环调用,我可以在某处停止绑定吗?

导入QtQuick 2.15 导入 QtQuick.Window 2.15 导入 QtQuick.Controls 2.15 窗户 { 宽度:640 身高:480 可见:真实 标题:qsTr(“你好世界”) 房地产 in anu...

回答 1 投票 0

在 C# 代码而不是 XAML 中声明的 WPF 属性

由于某些特殊原因,我在 C# 代码中声明了一个绑定,而不是像往常一样在 XAML 中声明它。我面临的问题是,当我仅更改对象的一个属性时,

回答 1 投票 0

Winforms datagridview - 可变列数 - INotifyPropertyChanged

假设我有两门课: 公共课时间:INotifyPropertyChanged { 公共整型值 { // ... } // INotifyPropertyChanged 实现 } 公开课日 { 噗...

回答 1 投票 0

Oracle 表单挂起问题

表单在 Forms_ddl('commit') 代码后被挂起,我正在关闭整个应用程序并再次打开以进行操作。 我们如何解决这个问题。 这个问题偶尔会发生。 那...

回答 1 投票 0

使用 8.2.2 MVVM CommunityToolkit 从侧线程更新 UI

当我修改变量时,UI 不会更新。更新变量的函数是由另一个线程中触发的事件触发的。 我试图回到主线程

回答 1 投票 0

POCO 的静态 INotifyPropertyChanged 生成器

找到了这个运行时INotifyPropertyChanged生成器 http://www.codeproject.com/Articles/141732/Automatic-Implementation-of-INotifyPropertyChanged 想知道是否有静电发生器可以避免......

回答 2 投票 0

如何在C# 6.0中实现INotifyPropertyChanged?

这个问题的答案已被编辑为在 C# 6.0 中,INotifyPropertyChanged 可以通过以下 OnPropertyChanged 过程实现: protected void OnPropertyChanged([

回答 4 投票 0

WinUI 3 数据绑定适用于一个对象,但不适用于另一个对象

我在 WinUI 数据绑定和 INotifyPropertyChanged 实现方面遇到问题。 我有一个按预期工作的测试类 公共类 BasicNotifyChange : INotifyPropertyChan...

回答 1 投票 0

如何引发属性更改事件来触发其他属性

我不确定我的标题是否正确。我有两个双精度属性,它们绑定到 2 个文本框,并且我想在一个属性更改时计算它们的总数。 RemainingBalance 属性是...

回答 2 投票 0

© www.soinside.com 2019 - 2024. All rights reserved.