Windows Presentation Foundation(WPF)应用程序的新增和改进的DataGrid控件。可以绑定到多个数据源。灵活的可编程渲染选项,以匹配自定义用户界面。
带有标题“*”的 DataGridColumn 已存在于 DataGrid 的 Columns 集合中
我有一个采用 MVVM 模式的 WPF 应用程序。在我的一种观点中,我必须绑定一个 ObservableCollection 来查看。在该视图中,我有一个 ListBox 和一个 DataGrid 都绑定到同一个 ObservableColl...
WPF 4 DataGrid:将行号放入 RowHeader
我希望将行号放入 WPF 4 DataGrid 的 RowHeader 中,以便它有一个类似于 Excel 的列用于显示 DataGrid 的行号。 我在网上看到的解决方案建议
我有一个 DataGrid,第一列作为文本列,第二列作为复选框列。我想要的是,如果我单击复选框。应该检查一下。 但是,需要单击两次才能被选中,对于
所以我有一个 CSV 文件: 标头 1、标头 2、标头 3、标头 4 数据11、数据12、数据13、数据14 数据21、数据22、数据23、数据24 数据31、数据32、数据33、数据34 数据41、数据42、数据43、数据44 和一个数据...
升级到.NET 4.5:ItemsControl与其项目源不一致
我正在构建一个应用程序,它使用许多 ItemControls(数据网格和列表视图)。为了轻松地从后台线程更新这些列表,我使用了 ObservableCollections 的扩展,其中...
我需要知道用户何时对 WPF 数据网格进行排序。 为什么没有排序事件?我只能找到排序事件。 我还研究了 CollectionView 和 ListCollectionView
我使用 WPF DataGrid 控件来显示一些详细信息和选择按钮,并且不需要左侧的灰色选择器列。这也破坏了我设计的美感。 有没有...
关闭 RecognizesAccessKey 的 WPF DataGrid
我有一个非常基本的 WPF 应用程序,并附有 MS SQL 服务器作为数据源。我的数据网格声明如下: 我有一个非常基本的 WPF 应用程序,并附有 MS SQL 服务器作为数据源。我的数据网格声明如下: <DataGrid HorizontalAlignment="Left" Margin="10,88,0,0" VerticalAlignment="Top" Height="456" Width="1018" ItemsSource="{Binding}" /> 当我运行应用程序时,我看到数据从数据库加载到网格中,但列标题看起来很奇怪。每个最初包含下划线的标题都删除了该下划线:some_title 变为 sometitle。 我发现这是因为下划线被识别为控制符号,将下一个符号变成助记符。 如何禁用此行为? 我发现如果你将单下划线加倍,即 some__title 而不是 some_title,则可以绕过此行为。但由于我的数据源是外部数据库,我无法影响它。或者也许用转换器? 我认为最好的方法是将属性RecognizesAccessKey转为false,但不幸的是它无法访问。 我是 WPF 新手,感谢您的帮助! 附注她是史努比的照片(如果有帮助的话) 编辑:我的目标框架是.net 4.5 尽管这是一个老问题,但我找到了解决方案。它可能对某人有帮助。 <DataGrid HorizontalAlignment="Left" Margin="10,88,0,0" VerticalAlignment="Top" Height="456" Width="1018" ItemsSource="{Binding}" > <DataGrid.ColumnHeaderStyle> <Style TargetType="{x:Type DataGridColumnHeader}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="DataGridColumnHeader"> <Border> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="False" /> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> </DataGrid.ColumnHeaderStyle> </DataGrid> 我能想到的最佳解决方案是拦截 DataGrid 事件 AutoGeneratingColumn 并将所有下划线替换为两个下划线,如下所示: private void DataGrid_AutoGeneratingColumn_1(object sender, DataGridAutoGeneratingColumnEventArgs e) { string header = e.Column.Header.ToString(); // Replace all underscores with two underscores, to prevent AccessKey handling e.Column.Header = header.Replace("_", "__"); } 根据我的理解,(遗憾的是)不可能在不重新定义整个控制模板的情况下覆盖底层 RecognizesAccessKey 的 ContentPresenter 的值。 请参阅 msdn 论坛上的此主题:如何在标签上设置 RecognizesAccessKey 而不影响其他参数?. 您可以使用自定义列,当您使用自定义列时,您可以根据需要定义列标题。 要添加到已接受的答案中,如果您想保留数据网格的原始样式,请按如下所示操作,并将 ContentPresenter 的 RecognizeAccessKey 更改为 False。 <Style TargetType="{x:Type DataGridColumnHeader}"> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type DataGridColumnHeader}"> <Grid> <Themes:DataGridHeaderBorder BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" IsClickable="{TemplateBinding CanUserSort}" IsPressed="{TemplateBinding IsPressed}" IsHovered="{TemplateBinding IsMouseOver}" Padding="{TemplateBinding Padding}" SortDirection="{TemplateBinding SortDirection}" SeparatorBrush="{TemplateBinding SeparatorBrush}" SeparatorVisibility="{TemplateBinding SeparatorVisibility}"> <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="False" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Themes:DataGridHeaderBorder> <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left"> <Thumb.Style> <Style TargetType="{x:Type Thumb}"> <Setter Property="Width" Value="8"/> <Setter Property="Background" Value="Transparent"/> <Setter Property="Cursor" Value="SizeWE"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Thumb}"> <Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/> </ControlTemplate> </Setter.Value> </Setter> </Style> </Thumb.Style> </Thumb> <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right"> <Thumb.Style> <Style TargetType="{x:Type Thumb}"> <Setter Property="Width" Value="8"/> <Setter Property="Background" Value="Transparent"/> <Setter Property="Cursor" Value="SizeWE"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Thumb}"> <Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/> </ControlTemplate> </Setter.Value> </Setter> </Style> </Thumb.Style> </Thumb> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> 通过 XAML,您可以更改 DataGridColumnHeader 行为以禁用将“_”解释为特殊字符(以便保留它): <DataGrid.Resources> <Style TargetType="{x:Type DataGridColumnHeader}"> <Setter Property="ContentTemplate"> <Setter.Value> <DataTemplate > <TextBlock Text="{Binding}" /> </DataTemplate> </Setter.Value> </Setter> </Style> </DataGrid.Resources>
我想将字符串绑定格式化为 Amount is X,其中 X 是绑定到标签的属性。 我见过很多例子,但以下不起作用: 我想将字符串绑定格式设置为 Amount is X,其中 X 是绑定到标签的属性。 我见过很多例子,但以下不起作用: <Label Content="{Binding Path=MaxLevelofInvestment, StringFormat='Amount is {0}'}" /> 我也尝试过这些组合: StringFormat=Amount is {0} StringFormat='Amount is {}{0}' StringFormat='Amount is \{0\}' 我什至尝试将绑定属性的数据类型更改为 int、string和 double。似乎什么都不起作用。这是一个非常常见的用例,但似乎不受支持。 这不起作用的原因是 Label.Content 属性的类型为 Object,并且 Binding.StringFormat 仅在绑定到 String 类型的属性时使用。 发生的事情是: Binding 正在对您的 MaxLevelOfInvestment 值进行装箱并将其存储为 Label.Content 属性作为装箱的十进制值。 标签控件有一个包含 ContentPresenter 的模板。 由于未设置 ContentTemplate,因此 ContentPresenter 会查找为 DataTemplate 类型定义的 Decimal。当它找不到时,它会使用默认模板。 ContentPresenter 使用的默认模板通过使用标签的 ContentStringFormat 属性来呈现字符串。 有两种可能的解决方案: 使用 Label.ContentStringFormat 而不是 Binding.StringFormat,或者 使用 String 属性(例如 TextBlock.Text)而不是 Label.Content 这里是如何使用Label.ContentStringFormat: <Label Content="{Binding Path=MaxLevelofInvestment}" ContentStringFormat="Amount is {0}" /> 以下是如何使用 TextBlock: <TextBlock Text="{Binding Path=MaxLevelofInvestment, StringFormat='Amount is {0}'}" /> 注意:为了简单起见,我在上面的解释中省略了一个细节:ContentPresenter实际上使用了自己的Template和StringFormat属性,但在加载过程中,它们会自动模板绑定到ContentTemplate和ContentStringFormat属性Label,所以看起来 ContentPresenter 实际上正在使用 Label 的属性。 制作一个通用的StringFormatConverter : IValueConverter。将格式字符串传递为 ConverterParameter. Label Content="{Binding Amount, Converter={...myConverter}, ConverterParameter='Amount is {0}'" 此外,当格式字符串中需要多个对象时,请使用 StringFormatMultiConverter : IMultiValueConverter,例如 Completed {0} tasks out of {1}。 我刚刚检查过,由于某种原因它不适用于 Label,可能是因为它在内部使用 ContentPresenter 来表示 Content 属性。您可以使用 TextBlock 来代替,这样就可以了。如果您需要继承样式、行为等,您也可以将下面的 TextBlock 摘录放在 Label 的内容中。 <TextBlock Text="{Binding Path=MaxLevelofInvestment, StringFormat='Amount is \{0\}'} /> 尝试使用转换器...... <myconverters:MyConverter x:Key="MyConverter"/> <Label Content="{Binding Path=MaxLevelofInvestment, Converter={StaticResource MyConverter"} /> public class MyConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return String.Format("Amount is {0}", value); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return value; } }
我正在创建一个 WPF 数据网格,我希望能够通过拖放对行重新排序,如下所示:我单击一行并将其向上或向下拖动。正如我所做的那样,一个标记显示了该行将被放置的位置...
在 AddNew 或 EditItem 事务 mvvm 期间不允许 WPF DataGrid“刷新”
我有以下网格 我有以下网格 <DataGrid x:Name="TablesDataGrid" Grid.Column="0" Grid.Row="1" ItemsSource="{Binding FilteredModels.View}" AlternationCount="2" AutoGenerateColumns="False" CanUserSortColumns="True" CanUserReorderColumns="False" CanUserDeleteRows="False" CanUserAddRows="False" SelectionMode="Extended" IsReadOnly="False" SelectionUnit="FullRow" RowHeight="25" HorizontalAlignment="Stretch" ColumnWidth="Auto"> <DataGrid.Columns > <DataGridCheckBoxColumn Width="*" Binding="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" IsReadOnly="False"> <DataGridCheckBoxColumn.HeaderTemplate> <DataTemplate> <CheckBox IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.CheckAll}"/> </DataTemplate> </DataGridCheckBoxColumn.HeaderTemplate> </DataGridCheckBoxColumn> <DataGridTextColumn Header="Source Table" Binding="{Binding SourceTableFullName}" Width="4*"></DataGridTextColumn> <DataGridTextColumn Header="EDW Schema" Binding="{Binding SchemaName}" Width="2*"></DataGridTextColumn> <DataGridTextColumn Header="EDW Table" Binding="{Binding TableName}" Width="4*"></DataGridTextColumn> <DataGridTextColumn Header="Status" Binding="{Binding Status}" Width="*"></DataGridTextColumn> </DataGrid.Columns> </DataGrid> 然后我有一个 searchCommand 对视图模型中的 collectionViewSource FilteredModels 执行搜索,然后调用 this.FilteredModels.View.Refresh(); 当用户选中一些复选框并将网格发送到编辑模式,然后执行搜索时,我们会收到以下错误 WPF DataGrid 'Refresh' is not allowed during an AddNew or EditItem transaction 有没有办法在选中复选框时强制网格退出编辑模式,甚至单击搜索按钮或其他修复方法? 谢谢! 我知道现在回答已经太晚了...但对于正在寻找答案的人来说 按如下顺序使用 cancelEdit 或 commitEdit 方法两次 //用于提交 this.datagrid_layers.CommitEdit(); this.datagrid_layers.CommitEdit(); //取消 this.datagrid_layers.CancelEdit(); this.datagrid_layers.CancelEdit(); 有一个干净的 MVVM 解决方案可以解决这个问题。首先,您的 ViewModel 必须实现 IEditableObject 接口(无操作就足够了)。然而,这还不够,因为 DataGrid 不会听 IEditableObject.CancelEdit。 另一个问题是,ICollectionView和IEditableCollectionView都没有实现另一个。虽然只有 ICollectionView 可以刷新,但只有 IEditableCollectionView 可以提交/取消。幸运的是,CollectionViewSource.GetDefaultView返回的集合视图实现了both: // ViewModel.cs public class ItemVM : IEditableObject, INotifyPropertyChanged { } public class ModuleVM : INotifyPropertyChanged { ICollectionView Items { get; } public ModuleVM(ObservableCollection<ItemVM> items) { Items = CollectionViewSource.GetDefaultView(items); } public void RefreshSafely() { ((IEditableCollectionView)Items).CancelEdit(); // alterantively, CommitEdit() Items.Refresh(); } } 或者换句话说,您可以将 ICollectionView 投射到 IEditableCollectionView 并先调用 CancelEdit()。 您应该能够将所选项目转换为 IEditableObject 并对其调用 EndEdit,或调用网格 CancelEdit 方法。 这是我的解决方案,请根据您的需要进行调整。 private void CommitEditRefreshViewSafely() { ((IEditableCollectionView)MyCollectionViewList.View).CommitEdit(); MyCollectionViewList.View.Refresh(); }
我有一个 DataGrid,其中包含 XAML 列,如下所示: 我有一个 DataGrid,其中包含 XAML 列: <DataGridTextColumn Header="Time" Binding="{Binding Date, StringFormat='yyyy-MM-dd HH:mm:ss'}" SortMemberPath="Date" SortDirection="Descending" Width="130" CanUserResize="True" /> <DataGridTextColumn Header="Level" Binding="{Binding Level}" Width="60" CanUserResize="True" /> <DataGridTextColumn Header="Source" Binding="{Binding Logger}" Width="150" CanUserResize="True" /> <DataGridTextColumn Header="Message" Binding="{Binding Message}" Width="*" CanUserResize="True" /> 我将其绑定到 ObservableCollection<EalsLogEvent>,其中输入 EalsLogEvent.Date DateTime: public ObservableCollection<EalsLogEvent> LogEvents { get { return _logEvents; } } 网格视图模型使用计时器来刷新自身,网格的一切看起来都很好,除了在应用程序启动时首次加载时。然后,Time 列似乎按降序排序,但实际上是按升序排序。 为了正确排序,我必须单击列标题两次;第一次将顺序更改为升序,现在与列的内容匹配。第二次单击列标题会将其排序顺序更改回降序,这次它对列内容进行正确排序,即降序。 如果我在 _logEvents 刷新时使用 LINQ 对集合进行排序,我会丢失用户通过单击列标题为该列设置的任何顺序。如果我必须让视图告诉模型 LINQ 排序应该使用哪个顺序,那就有点糟糕了。 您可以在 XAML 中使用 CollectionViewSource 来定义默认排序。 假设我们有一个视图模型: public class ViewModel : INotifyPropertyChanged { public ObservableCollection<Item> Items { get; private set; } } 我们可以为 CollectionView 集合创建自定义 Items: <Window xmlns:l="clr-namespace:YourNamespace" xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"> <Window.DataContext> <l:ViewModel/> </Window.DataContext> <Window.Resources> <CollectionViewSource Source="{Binding Items}" x:Key="GridItems"> <CollectionViewSource.SortDescriptions> <scm:SortDescription PropertyName="Date" Direction="Descending"/> </CollectionViewSource.SortDescriptions> </CollectionViewSource> </Window.Resources> <DataGrid ItemsSource="{Binding Source={StaticResource GridItems}}" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Header="Time" Binding="{Binding Date, StringFormat='yyyy-MM-dd HH:mm:ss'}" Width="130" CanUserResize="True" /> <DataGridTextColumn Header="Level" Binding="{Binding Level}" Width="60" CanUserResize="True" /> <DataGridTextColumn Header="Source" Binding="{Binding Logger}" Width="150" CanUserResize="True" /> <DataGridTextColumn Header="Message" Binding="{Binding Message}" Width="*" CanUserResize="True" /> </DataGrid.Columns> </DataGrid> </Window> 使用这种方法,您的底层源集合(本例中为Items)将不会受到影响,排序仅发生在视图中。 正如您可以在 MSDN 中阅读的那样: 您可以将集合视图视为绑定顶部的层 源集合,允许您导航和显示 基于排序、过滤和分组查询的集合,全部无需 必须操纵底层源集合本身。如果 源集合实现了 INotifyCollectionChanged 接口, CollectionChanged 事件引发的更改将传播到 意见。 您还应该注意以下事项: 所有集合都有一个默认的 CollectionView。 WPF 始终绑定到 视图而不是集合。如果直接绑定到集合, WPF 实际上绑定到该集合的默认视图。 因此,使用 CollectionViewSource,您只需为您的集合定义一个自定义视图。 您应该在视图模型中创建 2 个属性: private ObservableCollection<EalsLogEvent> logEvents = new ObservableCollection<EalsLogEvent>(); private ICollectionView logEventsView; public ObservableCollection<EalsLogEvent> LogEvents { get { return this.logEvents; } set { this.SetProperty(ref this.logEvents, value); } } public ICollectionView LogEventsView { get { if (this.logEventsView == null) { this.logEventsView= CollectionViewSource.GetDefaultView(this.LogEvents); this.logEventsView.SortDescriptions.Add(new SortDescription("Time", ListSortDirection.Descending)); } return this.logEventsView; } } 将 DataGrid 绑定到 LogEventsView,并使用 LogEvents 添加或删除项目。 这允许默认排序和用户排序。
选择datagrid标题中的所有复选框及其在wpf mvvm中的绑定
我正在研究wpf(mvvm架构)。我正在使用数据网格列出复选框,并在标题中单击“全选”复选框,我希望选中所有复选框,反之亦然......
如何在WPF C#中获取dataGrid中单元格的大小和位置
我已经开始在 WPF 中使用 dataGrid,但是来自 WinForm,它与我习惯的有点不同.. 我现在的问题是我需要获取特定单元格的矩形(这样我就可以
在我的 .NET 3.5 WPF 应用程序中,我有一个 WPF DataGrid,它将填充 500 列和 50 行。 App 的性能在滚动时非常非常差,或者当我执行 DataGrid.Items.Refres 时...
WPF DataGrid(MultiSelector?)多次引发 SelectedItems CollectionChanged 事件
我不确定这是否是 DataGrid 控件或 MultiSelector 的问题,但是当我在网格中选择多行时,每个单行都会触发 CollectionChanged 事件...
WPF Datagrid DataGridTextColumn 不允许小数
我无法在 DataGridTextColumn 中输入十进制值。如果 UpdateSourceTrigger = PropertyChanged,下面的链接建议我们不能输入小数值。 WPF DataGridTextColumn 绑定不&...
WPF DataGrid不在PropertyChanged上更新
使用NotifyPropertyChanged单击按钮更新我的数据网格时出现问题。如果我在后面的代码中设置了DataGrid.ItemsSource,它会起作用,但是如果我在xaml中设置它,它将不起作用。这是一些...
当选定的单元格位于该行时设置WPF DataGrid行标题的样式?
我有一个WPF DataGrid,它配置为仅允许单个单元格选择,即:-SelectionMode =“ Single” SelectionUnit =“ Cell”我想要做的是更改...的行标题的背景。