wpf datagrid colum实际晶体不正确 - 等待observableCollection完成更新
我有点问题。我有一个datagrid,其物品库是由观测值授予的。 (我正在创建一个小插件以进行修订)。
我的ObservableCollection包含一些在Revit进行选择时创建的元素。我的目标是创建一个带有文本框的stackpanel,其确实与已设置为自动的实际列的高度相同。
当我调试整个过程时,它运行较慢,并且得到这样的结果(我想在没有调试模式的情况下获得):
popup.DataGridSelectedObjects.UpdateLayout();
popup.DataGridSelectedObjects.Items.Refresh();
Thread.Sleep(2000)
public void AddRegexItemToStackpanel(string parameterName, DataGridColumn dc)
{
TextBox printTextBlock = new TextBox();
printTextBlock.Width = dc.ActualWidth;
printTextBlock.Margin = new Thickness(0.5, 0, 0, 0);
printTextBlock.Name = dc.Header.ToString().Replace("__", "_");
StackRegexPanel.Children.Add(printTextBlock);
}
是否有任何方法可以等待观察力授权正确更新?
非常感谢 詹妮斯
I´m kind of stuck here with a little problem. I´ve got a DataGrid whose ItemSource is fed by an ObservableCollection. (I´m creating a little plugin for Revit).
My ObservableCollection contains of some Elements which are created when doing a selection in Revit. It is my goal to create a Stackpanel with Textboxes, which do have the same height as the actualized Columnwidths, which are set to Auto.
When running the code in "normal" speed I get a result like this:
When I debug the whole process it runs slower and I get a result like this (Which I want to get without debug mode):
popup.DataGridSelectedObjects.UpdateLayout();
popup.DataGridSelectedObjects.Items.Refresh();
Thread.Sleep(2000)
public void AddRegexItemToStackpanel(string parameterName, DataGridColumn dc)
{
TextBox printTextBlock = new TextBox();
printTextBlock.Width = dc.ActualWidth;
printTextBlock.Margin = new Thickness(0.5, 0, 0, 0);
printTextBlock.Name = dc.Header.ToString().Replace("__", "_");
StackRegexPanel.Children.Add(printTextBlock);
}
Is there any method to wait the Observablecollection to update properly?
Thanks a lot and kind regards,
Jannis
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您应该使用其他方法。使用数据绑定应该是最直观的。避免使用XAML的XAML可能会使生活大部分时间都变得更加困难,并且您的代码会开始闻到。
您的
thread.sleep
看起来也非常可疑。还应避免调用updateLayout()
和 items.refresh()以提高性能。更改数据源(
observableCollection
)已经触发了刷新,并在必要时是完整的布局通行证。无需第二次触发这两个。它只会使您的UI慢。在下面您找到两个示例:静态,硬编码版本和一个更优雅,更具动态的版本(在其中自动添加文本框以匹配列计数)。
如果调整了列的大小(使用数据绑定时,则两个示例将自动调整每个
TextBox
的宽度(作为奖励)。这些示例还强调了WPF中数据结合的效率。避免数据绑定和XAML时,代码总是会变得臭和过于复杂。要制作
textbox
以遵循其各自列的宽度,只需使用数据绑定:为了使其动态,只需使用
itemscontrol
即可配置为水平显示其项目:在这两种情况下,您都应实现
ivalueconverter
以从double
转换为厚度
(对于Margin
)并绑定第一个示例的stackpanel.margin
iteg> itemscontrol.margin
在datagrid.rowheaderacheractualwidth
属性> 的属性属性>用于调整行header的属性(正确对齐文本框)。因为您提供了更多信息,所以我认为需要删除或调整我的答案:
要动态更改列计数,您应该始终将
DataTable
用作数据源。我添加了一种扩展方法,该方法将集合转换为DataTable
,以防万一。由于
textbox
元素旨在根据其关联的列过滤,因此我建议修改datagrid.columnheaderstyle
以将textbox
添加到列标题。这将更加方便,因为textbox
现在将自动调整和移动(如果列拖动)。列的
textbox
将绑定到observableCollection
ofString> String> String
VALUTION(filter Expressions),其中每个项目的索引直接映射到列索引。处理colectionChanged
事件允许处理textbox
输入。mainwindow.xaml.cs
mainwindow.xaml
示例以显示如何修改列标题以添加
textbox
以及如何使用附件行为。datagrid
现在绑定到DataTable
,以便动态添加/删除列。datagridcolumnfilter.cs
附加行为以映射
textbox
列标题的元素到集合(数据源) - 方向是一种方式,更新是在textbox.lostfocus
上发送的。我的建议是扩展
datagrid
,以摆脱这种附带的行为,并为控制处理增加更多便利性。如果仅与视图相关(通常是这种情况),即您不打算根据过滤修改数据源,我建议将过滤逻辑移动到附加的行为(或扩展
datagrid
)。这将使您的模型保持清洁。ExtensionMethods.cs
扩展方法将
iEnumerable< tdata>
转换为datatable
。user.cs
用于创建
dataTable
的数据模型在上面的示例中( mainwindow.xaml.cs )。该类还提供了一个有关如何使用属性
ignoreatTribute
控制的示例
属性/列的可见性和
system.com.ponentmodel.displayname
以重命名属性/列。nighoreatTribute.cs
You should use a different approach. Using data binding should be the most intuitive. Avoiding XAML where XAML is possible will make life a lot harder most of the time and your code will start to smell.
Your
Thread.Sleep
looks very very suspicious too. It's also very likely that callingUpdateLayout()
andItems.Refresh()
should be avoided to improve the performance.Changing the data source (
ObservableCollection
) will already trigger a refresh and, if necessary, a complete layout pass. No need to trigger both a second time. It will only make your UI slow.Below you find two examples: a static, hard-coded version and a more elegant and dynamic version (where text boxes are added automatically to match the column count).
Both examples will automatically adjust the width of each
TextBox
if columns are resized (as a bonus when using data binding). The examples also highlight the efficiency of data binding in WPF. Code will always become smelly and overly complex when avoiding data binding and XAML.To make a
TextBox
to follow the width of its respective column, simply use data binding:And to make it dynamic, simply use an
ItemsControl
that is configured to display its items horizontally:In both cases you should implement an
IValueConverter
to convert fromdouble
toThickness
(for theMargin
) and bind theStackPanel.Margin
of the first example or theItemsControl.Margin
of the second example to theDataGrid.RowHeaderActualWidth
property to adjust for the row header (to align the text boxes properly).Because you have provided more information, I felt the need to either delete or adjust my answer:
To dynamically change column count, you should always use a
DataTable
as data source. I have added an extension method that converts a collection to aDataTable
, in case you need it.Since the
TextBox
elements are meant to filter based on their associated column, I would suggest to modify theDataGrid.ColumnHeaderStyle
to add aTextBox
to the column header. This will be more convenient as theTextBox
will now automatically resize and move (in case the column is dragged).The column's
TextBox
will bind to aObservableCollection
ofstring
values (filter expressions), where the index of each item maps directly to a column index. Handling theColectionChanged
event allows to handle theTextBox
input.MainWindow.xaml.cs
MainWindow.xaml
Example to show how to modify the column header to add a
TextBox
and how to use the attached behavior. TheDataGrid
now binds to aDataTable
in order to allow to add/remove columns dynamically.DataGridColumnFilter.cs
Attached behavior to map the
TextBox
elements of the column headers to a collection (data source) - direction is one way and update is send onTextBox.LostFocus
.My recommendation is to extend
DataGrid
to get rid of this attached behavior and to add more convenience to the control handling.If filtering is only view related (which is usually the case) i.e. you don't intend to modify the data source based on the filtering, I recommend to move the filtering logic to the attached behavior (or extended
DataGrid
). This will keep your models clean.ExtensionMethods.cs
Extension method to convert a
IEnumerable<TData>
to aDataTable
.User.cs
The data model used to create the
DataTable
from in the above example (MainWindow.xaml.cs).The class also gives an example on how to use the attributes
IgnoreAttribute
to controlthe visibility of properties/columns and
System.ComponentModel.DisplayName
to rename the property/column.IgnoreAttribute.cs