什么是最好的表提供操作(如交换单元格,行,列)数据
本文关键字:单元格 交换 数据 操作 什么 | 更新日期: 2023-09-27 18:11:27
我正在一个使用MVVM-Pattern的WPF项目中工作。
直到现在一切都很好,但现在我面临一个丑陋的设计问题。为了显示我的数据,我像其他人一样使用DataGrid
,但我的ItemsSource
是List<List<MyClass>>
,因为我需要通过DataTemplate
显示整个对象。在我的DatagridCells
我得到这也工作,但现在我需要重新排序我不存在的列后一些ui条目,但这将是一个痛苦,所以想知道什么样的表类你会用来提供这些对象?我需要能够做什么(在容易编程):
- 访问每个cell <
- 重新排序/交换列/gh><
- 重新排序/交换行/gh>
现在看到它不是那么容易理解我实际上在这里做一些进一步的信息。
因为他们不明白List<List<MyClass>>
是什么它只不过是MyClass[,]
@Charleh "How do you reorder non-existent columns?"
问得好……如果你仔细阅读你会发现我需要一种新的类型的数据提供程序也就是一个真正的表而不是我的List<List<MyClass>>
没有列因为如果你有这样的List<List<MyClass>>
让命名为MyListLister
你的MyListLister[0]
将是一个行MyListLister[0][0]
将是一个单元格
You mean you have a single column because you are using a data template to show the object?
我为每个代码创建DataGrid,因为它需要是动态的,因为用户可以根据组合框选择改变整个DataGrid的样式,每次选择后,我需要重新创建DataGrid并修改MyListLister,但要将其用作itemssource,我必须执行此hack
@HighCore Post the relevant XAML
没有真正有用的xaml所以我将在休息后提供一个简单的例子
很抱歉延迟给出示例,但这是我的简单示例
主窗口
XAML
<Window x:Class="TableToDataGrid.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Label Name="theElement"/>
</Window>
cs
private void Window_Loaded(object sender, RoutedEventArgs e)
{
theElement.Content = new MyUsercontrol();
}
MyUsercontrol
XAML
<UserControl x:Class="TableToDataGrid.MyUsercontrol"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vmv="clr-namespace:TableToDataGrid">
<UserControl.Resources>
<DataTemplate x:Key="MyCellTemplate" DataType="{x:Type vmv:myClass}">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</UserControl.Resources>
<Label Name="AddYourDataGridHere"/>
</UserControl>
cs
using System.Linq;
using System.Windows;
using System.Collections;
using System.Windows.Data;
using System.Windows.Controls;
using System.Collections.Generic;
namespace TableToDataGrid
{
/// <summary>
/// Interaktionslogik für MyUsercontrol.xaml
/// </summary>
public partial class MyUsercontrol : UserControl
{
DataGrid myDataGrid = new DataGrid();
public MyUsercontrol()
{
InitializeComponent();
var list = new List<List<myClass>>();
for (int row = 0; row < 3; row++)
{
var myRow = new List<myClass>();
for (int col = 0; col < 5; col++)
myRow.Add(new myClass() { ID = col, Name = "Row" + row + " Column:" + col });
list.Add(myRow);
}
#region the hack
for (int c = 0; c < 5; c++)
{
DataGridTemplateColumn column = new DataGridTemplateColumn();
var factory = new FrameworkElementFactory(typeof(ContentPresenter));
factory.SetBinding(ContentPresenter.ContentProperty, new Binding(string.Format("[{0}]", c.ToString())));
factory.SetValue(ContentPresenter.ContentTemplateProperty, this.FindResource("MyCellTemplate") as DataTemplate);
column.SetValue(DataGridTemplateColumn.CellTemplateProperty, new DataTemplate { VisualTree = factory });
myDataGrid.Columns.Add(column);
}
#endregion the hack
myDataGrid.ItemsSource = list.AsEnumerable<IEnumerable>();
myDataGrid.AutoGenerateColumns = false;
AddYourDataGridHere.Content = myDataGrid;
}
}
}
myClass.cs
namespace TableToDataGrid
{
public class myClass
{
public int ID { get; set; }
public string Name { get; set; }
}
}
如您所见,结果是一个普通的表。有没有人知道如何以更简单的方式(ItemsSource
)提供相同的结果,我将能够从上面做我的3点?
WiiMaxx,
听起来你是在尝试线性地显示一个深度对象图,这对于DataGrid来说是相当麻烦的。我能够通过在我的实体基类上继承DynamicObject来解决这个挑战(在这种情况下我使用实体框架)。如果你不熟悉DynamicObject你可以在这个链接
中了解它http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.aspx本质上,它允许你做的是使用属性包来存储动态属性,这些属性将在运行时使用动态类型在你的对象上来来去去。当您需要将图形平展以便在数据网格中显示时,这是一个很好的解决方案。您只需要确保覆盖TryGetMember和TrySetMember方法。当与数据绑定结合在一起时,这一点特别漂亮,因为您可以在运行时添加/删除成员,并且通过数据绑定,WPF将尝试通过那些被覆盖的方法访问/更新这些成员。
public class EntityBase : DynamicObject, INotifyPropertyChanged
{
public Dictionary<string, object> DynamicProperties { get; set; }
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
/// <param name="propertyName">The property that has a new value.</param>
protected virtual void OnPropertyChanged(string propertyName)
{
if (!HasProperty(propertyName))
{
return;
}
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
public bool HasProperty(string propertyName)
{
// Verify that the property name matches a real,
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)[propertyName] != null)
{
return true;
}
return false;
}
#endregion
#region Ctor
public EntityBase()
{
this.DynamicProperties = new Dictionary<string, object>();
}
#endregion
#region DynamicObject Overrides
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
string name = binder.Name.ToLower();
return this.DynamicProperties.TryGetValue(name, out result);
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
this.DynamicProperties[binder.Name.ToLower()] = value;
OnPropertyChanged(binder.Name);
return true;
}
#endregion
}
现在,使用这个作为你的模型类型的基类,你可以在运行时添加/删除成员,仍然利用WPF数据绑定。
那么接下来我们需要使图形变平。ViewModelBase下面的基类仅仅实现了INotifyPropertyChanged。
public class YourViewModel : ViewModelBase
{
private YourDeepObjectGraphClass _instance;
public YourDeepObjectGraphClass Instance
{
get { return _yourClass; }
set
{
_yourClass = value;
OnPropertyChanged("Instance");
}
}
public void FlattenGraph()
{
foreach (IEnumerable<DeepObjectGraphType> t in Instance.List)
{
((dynamic)Instance).YourDynamicProperty = t.SomeProperty;
}
}
}
现在在你的视图中,你可以设置一个绑定控件(ItemsControl, DataGrid)到'YourDynamicProperty'和WPF将渲染它为你提供你已经调用了扁图后InitializeComponent已经在你的代码中调用。
我希望这对你有帮助,如果你有任何问题请告诉我。