使用多重绑定将 2 个集合加入数据网格
Joining 2 collections into datagrid using multibinding
我有 2 个数据集合,第一个仅用于组名,第二个用于值。
我想像这样将这些数据填充到数据网格中:
groupId | group | store 1 | store 2 | store 3 | store 4
1 | grp 1 | | | |
2 | grp 2 | | | |
3 | grp 3 | | | |
4 | grp 4 | | | |
我在模型视图中创建了一个新的 属性,它创建了所需行的新集合。
然后我尝试使用像这样的多重绑定和转换器来实现它。
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn Header="groupId" Binding="{Binding groupId}" IsReadOnly="True" />
<DataGridTextColumn Header="group" Binding="{Binding groupName}" IsReadOnly="True" />
<DataGridTextColumn Header="store 1" Binding="{Binding s1}" />
<DataGridTextColumn Header="store 2" Binding="{Binding s2}" />
<DataGridTextColumn Header="store 3" Binding="{Binding s3}" />
<DataGridTextColumn Header="store 4" Binding="{Binding s4}" />
</DataGrid.Columns>
<MultiBinding Converter="{StaticResource GroupsToValuesConverter}">
<Binding Path="Groups"></Binding>
<Binding Path="Values"></Binding>
</MultiBinding>
</DataGrid>
但是出现了这个错误。
Additional information: A 'MultiBinding' cannot be used within a
'ItemCollection' collection. A 'MultiBinding' can only be set on a
DependencyProperty of a DependencyObject.
我相信可以通过这种方式完成,但这里漏掉了一步。
我是 WPF 的新手,非常感谢您的帮助。
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
ObservableCollection<GroupStoreRow> retValue = new ObservableCollection<GroupStoreRow>();
IEnumerable<Group> groups = (IEnumerable<Group>)values[0];
Store o = (Store)values[1];
foreach (Person group in groups)
{
int GroupId = (int)group.GroupId;
GroupStoreRow c = new GroupStoreRow(GroupId, group.Name, group.SortOrder);
if (o != null)
{
if (o.Store1.ContainsKey(groupId))
{
c.Amount1 = (int)o.Store1[groupId].Amount ;
c.Capacity1 = (int)o.Store1[groupId].Capacity ;
}
if (o.Store2.ContainsKey(groupId))
{
c.Amount2 = (int)o.Store2[groupId].Amount ;
c.Capacity2 = (int)o.Store2[groupId].Capacity ;
}
if (o.Store3.ContainsKey(groupId))
{
c.Amount3 = (int)o.Store3[groupId].Amount ;
c.Capacity3 = (int)o.Store3[groupId].Capacity ;
}
}
retValue.Add(c);
}
return retValue;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
和这个 GroupStoreRow class
class GroupStoreRow : BindableBase
{
private bool hasChanged = false;
private int _amount1, _capacity1;
private int _amount2, _capacity2;
private int _amount3, _capacity3;
public int GroupID { get; private set; }
public string GroupName { get; private set; }
public int SortOrder { get; private set; }
public GroupStoreRow(int groupId, string groupName, int sortOrder)
{
GroupID = groupId;
GroupName = groupName;
SortOrder = sortOrder;
}
public int Amount1
{
get { return _amount1; }
set
{
SetProperty(ref _amount1, value);
}
}
public decimal Capacity1
{
get { return _capacity1; }
set
{
SetProperty(ref _capacity1, value);
}
}
...
public bool Changed
{
get
{
return hasChanged;
}
}
protected override bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
bool returnValue = base.SetProperty<T>(ref storage, value, propertyName);
if (returnValue)
{
if (!hasChanged)
hasChanged = true;
}
return returnValue;
}
}
您可以设置 ItemsSource
和 MultiBinding
。所以你可以这样写。
<DataGrid>
<DataGrid.ItemsSource>
<MultiBinding Converter="{StaticResource MyMultiValConverter}">
<Binding Path="Objects" />
<Binding Path="Objects2" />
</MultiBinding>
</DataGrid.ItemsSource>
</DataGrid>
并且您应该仔细编写MultiValuesConverter
以达到预期的效果。例如它可以是这样的(只是加入两个集合)。其中 OwnObject
是我的 viewModel。
public class DGMultiValueConverter : IMultiValueConverter
{
#region IMultiValueConverter Members
public object Convert( object[] values, Type targetType, object parameter,
CultureInfo culture )
{
ObservableCollection<OwnObject> combinedCollection =
new ObservableCollection<OwnObject>();
foreach ( var item in values[0] as ObservableCollection<OwnObject> )
{
combinedCollection.Add( item );
}
foreach ( var item in values[1] as ObservableCollection<OwnObject> )
{
combinedCollection.Add( item );
}
return combinedCollection;
}
public object[] ConvertBack( object value, Type[] targetTypes, object parameter,
CultureInfo culture )
{
throw new NotImplementedException();
}
#endregion
}
我有 2 个数据集合,第一个仅用于组名,第二个用于值。
我想像这样将这些数据填充到数据网格中:
groupId | group | store 1 | store 2 | store 3 | store 4
1 | grp 1 | | | |
2 | grp 2 | | | |
3 | grp 3 | | | |
4 | grp 4 | | | |
我在模型视图中创建了一个新的 属性,它创建了所需行的新集合。
然后我尝试使用像这样的多重绑定和转换器来实现它。
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn Header="groupId" Binding="{Binding groupId}" IsReadOnly="True" />
<DataGridTextColumn Header="group" Binding="{Binding groupName}" IsReadOnly="True" />
<DataGridTextColumn Header="store 1" Binding="{Binding s1}" />
<DataGridTextColumn Header="store 2" Binding="{Binding s2}" />
<DataGridTextColumn Header="store 3" Binding="{Binding s3}" />
<DataGridTextColumn Header="store 4" Binding="{Binding s4}" />
</DataGrid.Columns>
<MultiBinding Converter="{StaticResource GroupsToValuesConverter}">
<Binding Path="Groups"></Binding>
<Binding Path="Values"></Binding>
</MultiBinding>
</DataGrid>
但是出现了这个错误。
Additional information: A 'MultiBinding' cannot be used within a 'ItemCollection' collection. A 'MultiBinding' can only be set on a DependencyProperty of a DependencyObject.
我相信可以通过这种方式完成,但这里漏掉了一步。
我是 WPF 的新手,非常感谢您的帮助。
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
ObservableCollection<GroupStoreRow> retValue = new ObservableCollection<GroupStoreRow>();
IEnumerable<Group> groups = (IEnumerable<Group>)values[0];
Store o = (Store)values[1];
foreach (Person group in groups)
{
int GroupId = (int)group.GroupId;
GroupStoreRow c = new GroupStoreRow(GroupId, group.Name, group.SortOrder);
if (o != null)
{
if (o.Store1.ContainsKey(groupId))
{
c.Amount1 = (int)o.Store1[groupId].Amount ;
c.Capacity1 = (int)o.Store1[groupId].Capacity ;
}
if (o.Store2.ContainsKey(groupId))
{
c.Amount2 = (int)o.Store2[groupId].Amount ;
c.Capacity2 = (int)o.Store2[groupId].Capacity ;
}
if (o.Store3.ContainsKey(groupId))
{
c.Amount3 = (int)o.Store3[groupId].Amount ;
c.Capacity3 = (int)o.Store3[groupId].Capacity ;
}
}
retValue.Add(c);
}
return retValue;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
和这个 GroupStoreRow class
class GroupStoreRow : BindableBase
{
private bool hasChanged = false;
private int _amount1, _capacity1;
private int _amount2, _capacity2;
private int _amount3, _capacity3;
public int GroupID { get; private set; }
public string GroupName { get; private set; }
public int SortOrder { get; private set; }
public GroupStoreRow(int groupId, string groupName, int sortOrder)
{
GroupID = groupId;
GroupName = groupName;
SortOrder = sortOrder;
}
public int Amount1
{
get { return _amount1; }
set
{
SetProperty(ref _amount1, value);
}
}
public decimal Capacity1
{
get { return _capacity1; }
set
{
SetProperty(ref _capacity1, value);
}
}
...
public bool Changed
{
get
{
return hasChanged;
}
}
protected override bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
bool returnValue = base.SetProperty<T>(ref storage, value, propertyName);
if (returnValue)
{
if (!hasChanged)
hasChanged = true;
}
return returnValue;
}
}
您可以设置 ItemsSource
和 MultiBinding
。所以你可以这样写。
<DataGrid>
<DataGrid.ItemsSource>
<MultiBinding Converter="{StaticResource MyMultiValConverter}">
<Binding Path="Objects" />
<Binding Path="Objects2" />
</MultiBinding>
</DataGrid.ItemsSource>
</DataGrid>
并且您应该仔细编写MultiValuesConverter
以达到预期的效果。例如它可以是这样的(只是加入两个集合)。其中 OwnObject
是我的 viewModel。
public class DGMultiValueConverter : IMultiValueConverter
{
#region IMultiValueConverter Members
public object Convert( object[] values, Type targetType, object parameter,
CultureInfo culture )
{
ObservableCollection<OwnObject> combinedCollection =
new ObservableCollection<OwnObject>();
foreach ( var item in values[0] as ObservableCollection<OwnObject> )
{
combinedCollection.Add( item );
}
foreach ( var item in values[1] as ObservableCollection<OwnObject> )
{
combinedCollection.Add( item );
}
return combinedCollection;
}
public object[] ConvertBack( object value, Type[] targetTypes, object parameter,
CultureInfo culture )
{
throw new NotImplementedException();
}
#endregion
}