2016-03-10 5 views
2

У меня есть 2 набора данных, первая из которых предназначена только для имен групп, а вторая для значений.Объединение двух коллекций в datagrid с использованием multibinding

Я хочу, чтобы заполнить эти данные в DataGrid, как это:

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> 

Но получил эту ошибку.

Дополнительная информация: A MultiBinding не может быть использована в коллекции 'ItemCollection'. «MultiBinding» может быть установлен только на DependencyProperty объекта 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 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; 
    } 
} 

ответ

3

Вы можете установить ItemsSource с MultiBinding. Поэтому вы можете написать что-то вроде этого.

<DataGrid> 
    <DataGrid.ItemsSource> 
     <MultiBinding Converter="{StaticResource MyMultiValConverter}"> 
      <Binding Path="Objects" /> 
      <Binding Path="Objects2" /> 
     </MultiBinding> 
    </DataGrid.ItemsSource> 
</DataGrid> 

И вы должны тщательно писать MultiValuesConverter для того чтобы достигнуть желаемого эффекта. Например, это может быть так (просто объединение двух коллекций). Где OwnObject - мой взглядМодель.

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 
} 
+0

Большое вам спасибо, сейчас работает. Но Convertback не работает, я попытался добавить Mode = «TwoWays» для всех привязок, но все равно не уволен. Есть ли у вас какие-либо идеи? – Caesar

+0

Он работает, если вы пишете 'dgTest.ItemsSource = new ObservableCollection ();' что предполагает изменение 'ItemsSource'' DataGrid' и запуск 'ConvertBack'. И вы должны установить 'Mode =" TwoWays "' для объекта MultiBinding', а не привязки внутри него. Но я думаю, что это не то, что вы хотите. Пожалуйста, объясните, что вы хотите добиться, обратившись обратно? Или вы спрашиваете, как писать 'ConvertBack'? – bars222

+0

Я ожидаю, что когда пользователь изменит значение в datagrid, 'ConvertBack' будет запущен, поэтому я могу применить изменения к таблице Store. Я прочитал об этой проблеме в Интернете, и мне предложили, чтобы в каждом разделе 'Binding' включался' MultiBinding' '' Mode = "TwoWays" ', но я не работал. Посмотрите, как выглядит мой конвертер в области вопросов. – Caesar