一个图形用户界面元素,用于显示数据的表格视图。
当出现验证错误时,我尝试更改 DataGridCell(在 WPF 工具包 DataGrid 中)的默认样式。 默认为红色边框。 我怎样才能放置自己的模板? 谢谢。
在“学生详细信息”列中,我想堆叠三列中的数据值:姓名、专业和年份。是否可以做到这一点,同时仍然保持按单个列过滤的能力......
根据表格(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>
我有这个自定义数据网格。我想要实现的是,当用户将鼠标放在 DataGrid 内部(没有最大高度)时,它应该允许滚动整个父组件...
如何控制作为 DataGrid 控件一部分显示在 / 中的水平或垂直滚动条的厚度? 我希望它们显示得比实际情况“更厚”
Winui3:有没有办法转换用作 ItemsSource 的集合的成员
我正在尝试完成与这个问题所要求的相同的任务,特别是这个答案,但我正在winui3中工作(特别是我正在使用CommunityToolkit DataGrid),并且似乎没有任何东西
我有一个带有 Ajax 的 ASP.NET 页面和一个数据网格(数据表)。数据网格的列中有搜索字段。 对于普通搜索字段,来自数据源的数据过滤如下: 我的数据...
下面是我用来从 api 获取数据并将其绑定到 materi ui 数据网格的代码。我使用的版本是“@mui/x-data-grid”:“^7.18.0”,
这发生在我的数据网格实体更改之前: 更改 =“@(args => onselectrowpremadeinfo(ProductCareInfo))” 通常我会使用bind-value:after,但我不明白如何传递...
DataGrid RowDetails 中的按钮需要两次点击,解决方法会中断双击
我有一个 DataGrid,其中有一个在 RowDetailsTemplate 中定义的按钮。问题是,当点击按钮时,第一次点击被DataGrid消耗来选择行,所以你需要点击...
更新项目时 ObservableCollection 不更新 DataGrid
我正在尝试反序列化 json 文件,然后使用生成的可观察集合来获取 Datagrid 控件。到这里一切都好。 当我尝试更新集合时,Datagrid 不是
在具有可编辑子项的列表视图中正确处理子项编辑(或取消子项编辑)
简介: 我正在尝试使用可编辑子项来实现列表视图控件。对于项目/子项目的就地编辑,我使用编辑控件。 我相信我已经成功地正确编码放置...
我一直在学习实现一个小型的ROR系统,并使用强大的Datagrid gem来过滤、排序、导出数据等。 今天,我一直在尝试迭代基于孩子的过滤器......
C# WPF 访问 DataGridTextColumn 标题内的 TextBox
我有这个代码。 我有这个代码。 <DataGridTextColumn Binding="{Binding nazwisko}" Header="Nazwisko" IsReadOnly="True" ElementStyle="{StaticResource verticalCenter}" FontSize="14" HeaderStyle="{StaticResource HeaderStyle}" Width="195"> <DataGridTextColumn.HeaderTemplate> <DataTemplate> <StackPanel> <Label VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Margin="-5,0,0,5" Content="{Binding Content, RelativeSource={RelativeSource Mode=TemplatedParent}}" Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Parent.ActualWidth}"/> <TextBox x:Name="txt_name" MinHeight="20" TextChanged="Filtr_TextChanged"/> </StackPanel> </DataTemplate> </DataGridTextColumn.HeaderTemplate> <DataGridTextColumn.CellStyle> <Style TargetType="DataGridCell"> <Setter Property="Foreground" Value="{Binding FontColor}"/> </Style> </DataGridTextColumn.CellStyle> 我想清除文本框“txt_name”中的值。我有按钮“重置”,当他被单击时,文本框应该被清除。我怎样才能做到这一点?请帮忙:(. 您可以将 TextBox 值绑定到 祖先 DataContext。 如果您有将 ViewModel 绑定为 DataContext 的 Window: public class MainWindowViewModel : ObservableObject { private string _headerText = "InitialValue"; public string HeaderText { get => _headerText; set => SetProperty(ref _headerText, value); } public IRelayCommand Reset { get; } public MainWindowViewModel() { Reset = new RelayCommand(OnReset); } private void OnReset() { HeaderText = string.Empty; } } 然后你可以像这样使用它: ... <DataGridTextColumn.HeaderTemplate> <DataTemplate> <StackPanel> <Label VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Margin="-5,0,0,5" Content="{Binding Content, RelativeSource={RelativeSource Mode=TemplatedParent}}" Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Parent.ActualWidth}"/> <TextBox x:Name="txt_value" Text="{Binding DataContext.HeaderText, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" MinHeight="20"/> </StackPanel> </DataTemplate> </DataGridTextColumn.HeaderTemplate> ... <Button Content="Reset" Command="{Binding Reset}"/> ...
我的 WPF 应用程序生成的数据集每次可能具有不同的列数。 输出中包含对将用于应用格式设置的每列的描述。 一个
如何按显示的、转换的值、未绑定源属性值对DataGridTextColumn进行排序?
如何按显示的、转换的值而不是绑定源属性值对 WPF DataGridTextColumn 进行排序?现在它按行视图模型中的整数值排序,而不是显示转换器返回的文本。我用...
Devextreme-Angular:在网格模式下自定义其他单元格模板
由于英语不是我的母语,我会尽量让事情变得非常简单并解释我的思路。 我们有一个 devextreme-角度 DataGrid 例子: 最终目标: 按
我有一个 DataGrid,第一列作为文本列,第二列作为复选框列。我想要的是,如果我单击复选框。应该检查一下。 但是,需要单击两次才能被选中,对于
每次状态值发生变化时,DevExtreme React DataGrid 都会重置为第 1 页
示例案例步骤: DataGrid 有 5 个页面,用户导航到第 3 页 用户单击按钮(在 DataGrid 组件外部),它会触发状态更改,该状态更改甚至与/连接/我们无关...
Mudblazor Datagrid,其中我的标题是固定的,第一列是粘滞左侧,而水平滚动固定标题第一列不固定
使用Mudblazor,在Datagrid中,我的标题是固定的,第一列是粘滞左侧,而水平滚动固定标题第一列标题不固定,并且它也会受到水平影响